using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Diagnostics;
using System.Data;
using RNChessBoardCommonTypes;
using RNChessRulesEngine.RNChessRulesExceptions;

//----------------------------------------
// Cool trick to simulate a typedef in C#
using BitBoard = System.UInt64;
using Piece = System.Int32;
//----------------------------------------

//---------------------------------------------------------------------------//
//																			 //
//			r  n  C  h  e  s  s  B  o  a  r  d  C  o  n  t  r  o  l			 //
//			=======================================================			 //
//						  (c) 2003 Chris R. Chapman							 //
//																			 //
//	Version:		1.0	Full												 //
//  Date:			May 2003												 //
//  Author:			Chris R. Chapman (chris@chapmanconsulting.ca)			 //
//  Description:	A chessboard GUI written in 100% .Net/C#, featuring		 //
//					a resizable board with adjustable colors and configurable//
//					images for pieces, as well as events for capturing player//
//					movement and illegal moves.								 //
//																			 //
//																			 //
// LICENSING:		Can be freely distributed and used as long as the		 //
//					following criteria are met:								 //
//																			 //
//					1) All copyright notices are kept intact;				 //
//					2) Product is not for commercial resale;				 //
//					3) Product is NOT used in conjunction with ANY GPLed or  //
//					   FSF software.  I cannot abide by their philosophies.  //
//					4) Credit for the control to me is made in some			 //
//					   conspicuous fashion, like an About box.				 //
//---------------------------------------------------------------------------//
namespace RNChessRulesEngine
{

    // GROUP: Rules Engine Event Delegates Forward Declaration
	public delegate void PawnPromotionEventHandler(object sender, PawnPromotionEventArgs e);
	// -- GROUP END --

	/// <summary>
	/// This class defines a rules engine for evaluating chess moves using bitboard algorithms,
	/// as well as providing methods and functions for importing and exporting relevant details
	/// about the positions on the board.
	/// </summary>
	public class ChessRulesEngine
	{
		// GROUP: Event Declarations & Accessors
		private event PawnPromotionEventHandler _pawnPromotionEvent = null;
		/// <summary>
		/// Event handler fired when a pawn reaches its eighth rank and requires promotion.
		/// </summary>
		public event PawnPromotionEventHandler PawnPromotion
		{
			add
			{
				_pawnPromotionEvent += value;
			}
			remove
			{
				_pawnPromotionEvent -= value;
			}
		}
		// -- GROUP END --
		
		// GROUP: Game State Variables and Collections
		private ArrayList _MoveHistory = new ArrayList();
		private bool _isMate = false;
		private int _fullMoves=0;
		// -- GROUP END --

		// GROUP: Type definitions
		/// <summary>
		/// Provides a datastore structure for keeping stateful information about the position of pieces
		/// on the virtual chessboard.
		/// </summary>
		private struct RNChess_Position
		{
			// Tracking bitboards for pieces
			public BitBoard whitePieces;
			public BitBoard blackPieces;
			public BitBoard rooksQueens;
			public BitBoard bishopsQueens;
			public BitBoard whitePawns;
			public BitBoard whiteKnights;
			public BitBoard whiteBishops;
			public BitBoard whiteRooks;
			public BitBoard whiteQueens;
			public BitBoard blackPawns;
			public BitBoard blackKnights;
			public BitBoard blackBishops;
			public BitBoard blackRooks;
			public BitBoard blackQueens;

			// King square positions
			public int blackKingSquare;
			public int whiteKingSquare;
			public bool blackKingMoved;
			public bool whiteKingMoved;
			public bool blackLRookMoved;
			public bool blackRRookMoved;
			public bool whiteLRookMoved;
			public bool whiteRRookMoved;

			// Check status
			public bool whiteKingCheck;
			public bool blackKingCheck;

			// Blocking bitboards
			public BitBoard blocker;
			public BitBoard RotateRight90;
			public BitBoard RotateLeft90;
			public BitBoard RotateRight45;
			public BitBoard RotateLeft45;
			public BitBoard RotateRight315;

			// En-passant flag
			public bool enPassantAvailable;

			// Last move SAN
			public string lastMoveSAN;
		}

		/// <summary>
		///	Structure used to record specific move-related events for each player's turn.
		/// </summary>
		private struct MoveHistoryItem
		{
			public int fromSquare;
			public int toSquare;
			public bool whiteLeftRookMoved;
			public bool whiteRightRookMoved;
			public bool whiteKingMoved;
			public bool whiteKingCheck;
			public bool blackLeftRookMoved;
			public bool blackRightRookMoved;
			public bool blackKingMoved;
			public bool blackKingCheck;
			public bool whiteCastlingMove;
			public bool blackCastlingMove;
			public bool enPassantCapture;
			public Piece movedPiece;
			public Piece capturedPiece;
			public Piece promotedPiece;
			public BitBoard postMoveBitBoard;
			public BitBoard preMoveBitBoard;
			public BitBoard prePieceTypeBitBoard;
		}

		/// <summary>
		/// Specifies how many degrees a bitboard should be rotated.
		/// </summary>
		private enum RotateBitBoardBy
		{
			Right90Degrees,
			Left90Degrees,
			Right45Degrees,
			Left45Degrees,
			A8H1Map,
			A1H8Map
		}
		// -- GROUP END --

		// GROUP: Application Fields
		/// <summary>
		/// The name or handle for the black-side player.
		/// </summary>
		public string BlackPlayerName = "";
		/// <summary>
		/// The name or handle for the white-side player.
		/// </summary>
		public string WhitePlayerName = "";
		/// <summary>
		/// Get/Set the current player turn.
		/// </summary>
		public PlayerTurn PlayerToMove;
		
		private int _blackCaptureCount = 0;
		/// <summary>
		/// Get the count of pieces black has captured.
		/// </summary>
		public int BlackCaptureCount
		{
			get { return _blackCaptureCount; }
		}
		
		private int _whiteCaptureCount = 0;
		/// <summary>
		/// Get the count of pieces white has captured.
		/// </summary>
		public int WhiteCaptureCount
		{
			get { return _whiteCaptureCount; }
		}

		/// <summary>
		/// Gets the current list of moves in standard algebraic notation (SAN).
		/// </summary>
		public string MovesList
		{
			get { return _sbSANMoveList.ToString(); }
		}

		// -- GROUP END --

		// GROUP: Piece Constants
		// Piece type definitons -- we can't apply a negation to enumerated types, so
		// I declared them as constants.  Not "Code Complete", but oh, well.
		// Piece == System.Int32 (signed 32-bit int)
		private const Piece NONE = ChessPieceDefinition.NONE;
		private const Piece PAWN = ChessPieceDefinition.PAWN;
		private const Piece KNIGHT = ChessPieceDefinition.KNIGHT;
		private const Piece BISHOP = ChessPieceDefinition.BISHOP;
		private const Piece ROOK = ChessPieceDefinition.ROOK;
		private const Piece QUEEN = ChessPieceDefinition.QUEEN;
		private const Piece KING = ChessPieceDefinition.KING;
		// -- GROUP END --

		// GROUP: SAN Variables
		private char[] _SANPieceCodes = new char[] { ' ','p','n','b','r','q','k' };
		// -- GROUP END --

		// GROUP: Application Constants
		/// <summary>
		/// Number of squares on a chessboard (8x8)
		/// </summary>
		public const int TOTAL_SQUARES = 64;
		public const int FILETOTAL_SQUARES = 8;
		// -- GROUP END --

		// GROUP: Chesspiece Square Constants
		private const int WHITE_KING_SQUARE = 60;
		private const int WHITE_KINGSIDE_CASTLE_TO = 62;
		private const int WHITE_QUEENSIDE_CASTLE_TO = 58;
		private const int WHITE_RROOK_CASTLE_FROM = 63;
		private const int WHITE_RROOK_CASTLE_TO = 61;
		private const int WHITE_LROOK_CASTLE_FROM = 56;
		private const int WHITE_LROOK_CASTLE_TO = 59;
		private const int BLACK_KING_SQUARE = 4;
		private const int BLACK_KINGSIDE_CASTLE_TO = 6;
		private const int BLACK_QUEENSIDE_CASTLE_TO = 2;
		private const int BLACK_RROOK_CASTLE_FROM = 7;
		private const int BLACK_RROOK_CASTLE_TO = 5;
		private const int BLACK_LROOK_CASTLE_FROM = 0;
		private const int BLACK_LROOK_CASTLE_TO = 3;
		// -- GROUP END --

		// GROUP: Virtual Board Array Definitions
		/// <summary>
		/// Virtual board with start positions.
		/// </summary>
		private Piece[] _virtualBoardInit = new Piece[64]
			{
				-ROOK,-KNIGHT,-BISHOP,-QUEEN,-KING,-BISHOP,-KNIGHT,-ROOK,
				-PAWN,-PAWN,-PAWN,-PAWN,-PAWN,-PAWN,-PAWN,-PAWN,
				NONE,NONE,NONE,NONE,NONE,NONE,NONE,NONE,
				NONE,NONE,NONE,NONE,NONE,NONE,NONE,NONE,
				NONE,NONE,NONE,NONE,NONE,NONE,NONE,NONE,
				NONE,NONE,NONE,NONE,NONE,NONE,NONE,NONE,
				PAWN,PAWN,PAWN,PAWN,PAWN,PAWN,PAWN,PAWN,
				ROOK,KNIGHT,BISHOP,QUEEN,KING,BISHOP,KNIGHT,ROOK
			};

		private Piece[] _virtualBoard = new Piece[64];
		/// <summary>
		/// Get/Set a 1D, 64 element array of Piece objects (Int32) representing the chessboard.
		/// </summary>
		public Piece[] VirtualBoard
		{
			get { return _virtualBoard; }
			set 
			{
				if(value.GetLength(0) > 64 || value.GetLength(0) < 64)
				{
					throw new ArgumentException("The virtual board array does not contain 64 elements.");
				}
				else
				{
					// Load the passed-in virtual board definition array, THEN reset the bitboards and
					// initialize them from the virtual board.
					LoadVirtualBoard(value);
					
					InitBitBoards();
				}
			}
		}


		// -- GROUP END --

		// GROUP: BitBoard and Virtual Board Variables
		/// <summary>
		/// Bitboard masks
		/// - these are bitboards with only one bit turned on for each square
		/// Bitboard masks are used in OR operations to track pieces in specific
		///	squares as indexed.  They correspond to the _virtualBoard array indices
		///	defined above.
		/// </summary>
		private BitBoard[] _bitMask = new BitBoard[64];
		private BitBoard _whiteFifthRankBitMask;
		private BitBoard _blackFifthRankBitMask;

		// Arrays of modifiers for calculating various piece movements-- these
		// are used in the population of the movement and attack bitboards
		private int[] KNIGHT_ATTACK_SQUARE = new int[8] {-17,-15,-10,-6,6,10,15,17};
		private int[] BISHOP_ATTACK_SQUARE = new int[4] {-9,-7,7,9};
		private int[] ROOK_ATTACK_SQUARE = new int[4] {-8,-1,1,8};
		private int[] PAWN_ATTACK_SQUARE = new int[2] {7,9};
		private int[] PAWN_MOVE_SQUARE = new int[2] {8,16};

		// These arrays contain indexes of squares used in castling
		private int[] WHITE_LCASTLE_SQ = new int[3] {59,58,57};
		private int[] WHITE_RCASTLE_SQ = new int[2] {61,62};
		private int[] BLACK_LCASTLE_SQ = new int[3] {3,2,1};
		private int[] BLACK_RCASTLE_SQ = new int[2] {5,6};

		// These arrays contain the bitboards for valid attacks for a 
		// piece on a particular square.
		private BitBoard[] _wPawnAttacks = new BitBoard[64];
		private BitBoard[] _bPawnAttacks = new BitBoard[64];
		private BitBoard[] _KnightAttacks = new BitBoard[64];
		private BitBoard[] _BishopAttacks = new BitBoard[64];

		//TODO: re-assign these arrays-- existing code actually checks
		//legal move squares but not whether they're occupied.
		private BitBoard[] _QueenAttacks = new BitBoard[64];
		private BitBoard[] _RookAttacks = new BitBoard[64];
		private BitBoard[] _KingAttacks = new BitBoard[64];

		// These arrays contain the valid move squares for 
		// various pieces.
		private BitBoard[] _wPawnMoves = new BitBoard[64];
		private BitBoard[] _bPawnMoves = new BitBoard[64];
		private BitBoard[] _RookMoves = new BitBoard[64];
		private BitBoard[] _BishopMoves = new BitBoard[64];
		private BitBoard[] _QueenMoves = new BitBoard[64];

		// These are probably not necessary-- represent
		// "discomfort zone" squares around the king
		private BitBoard[] _KingAttacks1 = new BitBoard[64];
		private BitBoard[] _KingAttacks2 = new BitBoard[64];

		// Blocking BitBoard Masks
		BitBoard _Blocker = new BitBoard();
		BitBoard _BlockerRotateRight90 = new BitBoard();
		BitBoard _BlockerRotateRight45 = new BitBoard();
		BitBoard _BlockerRotateRight315 = new BitBoard();

		// These bitboards are used as masks to determine positions in relation
		// to a given square
		private BitBoard[] _squarePlus_1 = new BitBoard[64];	// Square Right
		private BitBoard[] _squarePlus_7 = new BitBoard[64];	// Left-Forward Diagonal
		private BitBoard[] _squarePlus_8 = new BitBoard[64];	// Square Forward
		private BitBoard[] _squarePlus_9 = new BitBoard[64];	// Right-Forward Diagonal
		private BitBoard[] _squareMinus_1 = new BitBoard[64];	// Square Left
		private BitBoard[] _squareMinus_7 = new BitBoard[64];	// Square Right-Back Diagonal
		private BitBoard[] _squareMinus_8 = new BitBoard[64];	// Square Back
		private BitBoard[] _squareMinus_9 = new BitBoard[64];	// Square Left-Back Diagonal

		// -- GROUP END --

		// GROUP: Precomputation Variables
		// Rank and file attack lookup arrays -- each contains
		// the possible permutations of "attackable" squares from			
		// a given square (0-63) along a rank or file depending
		// on 256 possible states of occupation

		private BitBoard[,] _RankAttacks = new BitBoard[64,256];
		private BitBoard[,] _FileAttacks = new BitBoard[64,256];

		// Diagonal attack lookup arrays
		// NOTE:  These are jagged arrays as the number of "state"
		// permutations varies with the lengths of each diagonal 
		private BitBoard[][] _DiagonalA8H1Attacks = new BitBoard[64][];
		private BitBoard[][] _DiagonalA1H8Attacks = new BitBoard[64][];

		// -- GROUP END --

		private RNChess_Position _chessPosition = new RNChess_Position();
		private StringBuilder _sbSANMoveList = new StringBuilder();
		
		// GROUP: Initialization
		/// <summary>
		/// Constructor -- sets up the bitboards for each piece, attack squares and bitmasks
		/// for evaluating and constructing legal move calculations.
		/// </summary>
		public ChessRulesEngine()
		{
			
			//ResetBoard();			// Resets the virtual chessboard to initial game state
			InitChessPosition();	// Initialize struct for tracking pieces
			LoadVirtualBoard();		// Load the starting position for all the pieces
			InitBitmasks();			// Create single-bit bitmasks for each square on the board
			InitBitBoards();		// Initialize internal bitboards for tracking each piece		
			InitAttackBoards();		// Initialize internal attack bitboards for validating attack moves
            
			// Initialize starting player side
			PlayerToMove = PlayerTurn.White;
			Debug.WriteLine("Initialization of rules engine complete.");
		}

		/// <summary>
		/// Initializes the structure for keeping track of piece positions and movements.
		/// </summary>
		private void InitChessPosition()
		{
			_chessPosition = new RNChess_Position();
			ResetGameFlags();
		}
		// -- GROUP END --

		// GROUP: Debug Routines
		/// <summary>
		/// Returns a rudimentary string representation of a bitboard in an 8x8 grid.
		/// </summary>
		/// <param name="bitBoard"></param>
		/// <returns></returns>
		public string DisplayBitBoard(BitBoard bitBoard)
		{
			StringBuilder sb = new StringBuilder();

			for(int i=0; i<64; i++)
			{
				if((_bitMask[i] & bitBoard) != 0)
				{
					sb.Append("-X-");
				}
				else
				{
					sb.Append("-O-");
				}
				if( (i&7) == 7)
				{
					char newline = '\n';
					sb.Append(newline);
				}
			}

			return sb.ToString();
		}


		/// <summary>
		/// Returns string representation of bitboard with both black and white pieces shown
		/// in an 8x8 grid.
		/// </summary>
		/// <returns></returns>
		public string DisplayBitBoard()
		{
			BitBoard allPieces = (_chessPosition.whitePieces | _chessPosition.blackPieces);
			string tmp = DisplayBitBoard(allPieces);
			return tmp;
		}

		/// <summary>
		/// Provides a string representation of an array
		/// </summary>
		/// <param name="arrayToDisplay"></param>
		/// <returns></returns>
		public string DisplayIntArray(int[] arrayToDisplay)
		{
			StringBuilder sb = new StringBuilder();
			string item;
			int len = arrayToDisplay.GetLength(0);
			for(int x = 0; x<len; x++)
			{		   
				string pieceCode = GetSANPieceCode(arrayToDisplay[x]).ToString();
				if(arrayToDisplay[x]<0)
				{
					pieceCode = pieceCode.ToLower();
				}
				if(arrayToDisplay[x]==0) pieceCode=" ";
				
				pieceCode = "|" + pieceCode;
				if((x & 7)==7)
					pieceCode += "|\n";
				sb.Append(pieceCode);
			}

			return sb.ToString();
		}

		/// <summary>
		/// Debugging function that displays an ASCII representation of all the bitboards in
		/// the black pawn moves collection
		/// </summary>
		private void PrintBitBoards()
		{
			int cnt = 0;
			foreach(BitBoard bb in _bPawnMoves)
			{
				Debug.WriteLine("->" + cnt.ToString());
				Debug.WriteLine(this.DisplayBitBoard(bb));
				Debug.WriteLine("\n");
				cnt++;
			}
		}
		// -- GROUP END --
				
		// GROUP: General Commands
		
		/// <summary>
		/// Registers player names for each side
		/// </summary>
		/// <param name="whitePlayerName">Name for white player.</param>
		/// <param name="blackPlayerName">Name for black player.</param>
		public void RegisterPlayers(string whitePlayerName, string blackPlayerName)
		{
			WhitePlayerName = whitePlayerName;
			BlackPlayerName = blackPlayerName;
		}
		
		/// <summary>
		/// Resets the virtual chessboard to start game position
		/// </summary>
		public void ResetBoard()
		{
			InitChessPosition();
			LoadVirtualBoard();
			InitBitBoards();
			PlayerToMove = PlayerTurn.White;
			_blackCaptureCount = 0;
			_whiteCaptureCount = 0;
			if(_isMate)
			{
				_isMate = false;
			}

			// Clear and reset the notated move list, the move history collection and
			// full moves counter.
			_sbSANMoveList.Remove(0,_sbSANMoveList.Length);
			_MoveHistory.Clear();
			_fullMoves = 0;
		}

		/// <summary>
		/// Clears chessboard and sets each square to NONE
		/// </summary>
		public void ClearBoard()
		{
			IEnumerator virtSq = _virtualBoard.GetEnumerator();
			int c = 0;
			while(virtSq.MoveNext())
			{
				_virtualBoard[c] = NONE;
			}
			
			this.ResetBitBoards();
			this.ResetGameFlags();
		}

		/// <summary>
		/// Loads the rules engine with a position described in Forsyth-Edwards notation.
		/// </summary>
		/// <param name="FENPositionString">Valid FEN string.</param>
		public void LoadFENPosition(string FENPositionString)
		{
			try
			{
				// reset the rules engine and load new position into FEN analyzer
				// and virtual board
				ResetBoard();
				FENTranslator fen = new FENTranslator(FENPositionString);
				this.VirtualBoard = fen.ChessBoardArray;		
		
				PlayerToMove = fen.ActiveColor;
				if(!fen.BlackKingsideCastle) _chessPosition.blackRRookMoved = true;
				if(!fen.WhiteKingsideCastle) _chessPosition.whiteRRookMoved = true;
				if(!fen.BlackQueensideCastle) _chessPosition.blackLRookMoved = true;
				if(!fen.WhiteQueensideCastle) _chessPosition.whiteLRookMoved = true;
				
				// Update piece capture counters
				foreach(int sq in _virtualBoard)
				{
					if(sq > 0) _whiteCaptureCount++;
					if(sq < 0) _blackCaptureCount++;
				}

			}
			catch(Exception e)
			{
				throw new ChessRulesEngineException("Failed to load FEN position",e);
			}
		}

		/// <summary>
		/// Returns a FEN notation string representing the current state of the chessboard.
		/// </summary>
		/// <returns>FEN string.</returns>
		public string GetFENPosition()
		{
			FENTranslator fen = new FENTranslator(this.VirtualBoard);
			
			fen.ActiveColor = PlayerToMove;
			fen.FullMoveNumber = _fullMoves;

			if(_chessPosition.whiteKingMoved)
			{
				fen.WhiteKingsideCastle = false;
				fen.WhiteQueensideCastle = false;
			}
			else	
			{
				if(_chessPosition.whiteRRookMoved) fen.WhiteKingsideCastle = false;
				if(_chessPosition.whiteLRookMoved) fen.WhiteQueensideCastle = false;
			}

			if(_chessPosition.blackKingMoved)
			{
				fen.BlackKingsideCastle = false;
				fen.BlackQueensideCastle = false;
			}
			else
			{
				if(_chessPosition.blackRRookMoved) fen.BlackKingsideCastle = false;
				if(_chessPosition.blackLRookMoved) fen.BlackQueensideCastle = false;
			}

			return fen.ToString();
		}

		// -- GROUP END --

		// GROUP: Chessboard Functions
		/// <summary>
		/// Loads the virtual chessboard array with the initial configuration of pieces
		/// and sets the locations of the black and white king squares accordingly.
		/// </summary>
		private void LoadVirtualBoard()
		{
			_virtualBoardInit.CopyTo(_virtualBoard,0);
			SetKingSquarePositions();
		}

		/// <summary>
		/// Loads a given virtual chessboard array with configurations of pieces and sets the
		/// locations of the black and white king squares accordingly.
		/// </summary>
		/// <param name="virtualBoard">64-element array of type Piece (int32) specifying
		/// the locations of pieces on the chessboard.
		/// </param>
		private void LoadVirtualBoard(Piece[] virtualBoard)
		{
			if(virtualBoard.GetLength(0) < 64 || virtualBoard.GetLength(0) > 64)
			{
				throw new ArgumentException("The virtual board array is not 64 elements deep.");
			}
			virtualBoard.CopyTo(_virtualBoard,0);
			SetKingSquarePositions();
		}

		/// <summary>
		/// Determines where the black and white kings are located on the virtual chessboard
		/// and gets a fix on their position, storing the results in an internal state structure.
		/// </summary>
		private void SetKingSquarePositions()
		{
			for(int sq = 0; sq < TOTAL_SQUARES; sq++)
			{
				if(_virtualBoard[sq] == KING)
				{
					_chessPosition.whiteKingSquare = sq;
				}
				if(_virtualBoard[sq] == -KING)
				{
					_chessPosition.blackKingSquare = sq;
				}
			}
		}

		/// <summary>
		/// Returns the piece type occupying a given square on the virtual chessboard.
		/// </summary>
		/// <param name="square">Index (0-63) of the square to query.</param>
		/// <returns>Signed 32-bit Int representing the piece type and color.</returns>
		private Piece GetPiece(int square)
		{
			if(square < 0 || square >= 64)
			{
				return NONE;
			}
			else
			{
				return (Piece)_virtualBoard[square];
			}

		}

		
		/// <summary>
		/// Returns an ArrayList containing the indices (0-63) of pieces on a given BitBoard, 
		/// e.g. all the white pawns or all the black bishops.
		/// </summary>
		/// <param name="pieceBitBoard">BitBoard representing the locations of pieces to find.</param>
		/// <returns>ArrayList collection object containing the indices of the pieces found
		/// in the BitBoard.
		/// </returns>
		private ArrayList GetSquareIndices(BitBoard pieceBitBoard)
		{
			ArrayList indices = new ArrayList();
			for(int sq=0; sq < 64; sq++)
			{
				if((_bitMask[sq] & pieceBitBoard) != 0)
				{
					indices.Add(sq);
				}
			}

			return indices;
		}

		/// <summary>
		/// Returns the last item in the internal move history collection.
		/// </summary>
		/// <returns>MoveHistoryItem object.</returns>
		private MoveHistoryItem GetLastMoveItem()
		{
			if(_MoveHistory.Count==0)
			{
				throw new RNChessRulesExceptions.ChessRulesEngineException("Move history is empty.");
			}
			MoveHistoryItem mhi = (MoveHistoryItem)_MoveHistory[_MoveHistory.Count-1];
			return mhi;
		}
		
		/// <summary>
		/// Gets the color of the piece that is located on a given square.
		/// </summary>
		/// <param name="pieceSquare">Square (0-63) on the board to interrogate.</param>
		/// <returns>Side color for piece (black or white) if it exists.  Generates
		/// an ArgumentException otherwise.
		/// </returns>
		private PlayerTurn GetPieceColor(int pieceSquare)
		{
			if(pieceSquare < 0 || pieceSquare > 63)
			{
				throw new ArgumentException("PieceSquare must be between 0-63\n" + 
					pieceSquare.ToString() + " was entered into the GetPieceColor() function.");
			}

			Piece chessPiece = GetPiece(pieceSquare);
			if(chessPiece==NONE)
			{
				throw new ArgumentException("No piece exists on the requested square: " +
					pieceSquare.ToString());
			}
			return chessPiece < 0 ? PlayerTurn.Black : PlayerTurn.White;
		}

		
		/// <summary>
		/// Restores the king "check" flags for a retracted move.
		/// </summary>
		private void RestoreKingCheckFlags()
		{
			MoveHistoryItem firstPly = GetLastMoveItem();
					
			if(firstPly.blackKingCheck==true && _chessPosition.blackKingCheck==true)
			{
				_chessPosition.blackKingCheck = false;
			}
			else if(firstPly.whiteKingCheck==true && _chessPosition.whiteKingCheck==true)
			{
				_chessPosition.whiteKingCheck = false;
			}
			
			if(_MoveHistory.Count > 1) 
			{
				MoveHistoryItem secondPly = (MoveHistoryItem)_MoveHistory[_MoveHistory.Count-2];
				if(secondPly.blackKingCheck==true && _chessPosition.blackKingCheck==false)
				{
					_chessPosition.blackKingCheck = true;
				}
				else if(secondPly.whiteKingCheck==true && _chessPosition.whiteKingCheck==false)
				{
					_chessPosition.whiteKingCheck = true;
				}
			}
		}

		/// <summary>
		/// Restores the game state piece movement flags according to the conditions found in
		/// the last recorded move.
		/// </summary>
		private void RestorePieceMovedFlags()
		{
			MoveHistoryItem lastMove = GetLastMoveItem();

			// Restore first move flags for rook or king and check flags for king as required.
			if(lastMove.blackKingMoved == true && _chessPosition.blackKingMoved == true)
			{
				_chessPosition.blackKingMoved = false;
			}
			else if(lastMove.blackRightRookMoved == true && _chessPosition.blackRRookMoved == true)
			{
				_chessPosition.blackRRookMoved = false;
			}
			else if(lastMove.blackLeftRookMoved == true && _chessPosition.blackLRookMoved == true)
			{
				_chessPosition.blackLRookMoved = false;
			}
			else if(lastMove.whiteKingMoved == true && _chessPosition.whiteKingMoved == true)
			{
				_chessPosition.whiteKingMoved = false;
			}
			else if(lastMove.whiteLeftRookMoved == true && _chessPosition.whiteLRookMoved == true)
			{
				_chessPosition.whiteLRookMoved = false;
			}
			else if(lastMove.whiteRightRookMoved == true && _chessPosition.whiteRRookMoved == true)
			{
				_chessPosition.whiteRRookMoved = false;
			}
		}

		/// <summary>
		/// Updates the virtual chessboard to reflect moves.
		/// </summary>
		/// <param name="fromSquare">Index (0-63) of piece to move.</param>
		/// <param name="toSquare">Index (0-63) of piece destination.</param>
		private void UpdateVirtualBoard(int fromSquare, int toSquare)
		{
			_virtualBoard[toSquare] = _virtualBoard[fromSquare];
			_virtualBoard[fromSquare] = NONE;
		}
		
			
		/// <summary>
		/// Switches player sides for turn.
		/// </summary>
		private void SwitchSides()
		{			
			PlayerToMove = (PlayerToMove == PlayerTurn.White ? PlayerTurn.Black : PlayerTurn.White);
		}
				
		/// <summary>
		/// Validates syntax of algebraic coordinate expressions
		/// </summary>
		/// <param name="algebraicCoordinate"></param>
		/// <returns>true if formatted as [A-H][1-8]</returns>
		private bool ValidateAlgebraicCoord(string algebraicCoordinate)
		{
			return Regex.Match(algebraicCoordinate,"^[A-Ha-h][1-8]$").Success;
		}

		/// <summary>
		/// Returns the distance along a file (1-8) between the current and target squares
		/// </summary>
		/// <param name="currentSquareIndex"></param>
		/// <param name="targetSquareIndex"></param>
		/// <returns></returns>
		private int FileDistance(int currentSquareIndex, int targetSquareIndex)
		{
			int x = Math.Abs((targetSquareIndex/8)-(currentSquareIndex/8));
			return x;
		}


		/// <summary>
		/// Returns the distance along a rank (A-H) between the current and target squares
		/// </summary>
		/// <param name="currentSquareIndex"></param>
		/// <param name="targetSquareIndex"></param>
		/// <returns></returns>
		private int RankDistance(int currentSquareIndex, int targetSquareIndex)
		{
			return Math.Abs((targetSquareIndex&7)-(currentSquareIndex&7));
		}


		/// <summary>
		/// Returns either the FileDistance or RankDistance separating the
		/// currentSquare or targetSquare, whichever is greater.
		/// </summary>
		/// <param name="currentSquareIndex"></param>
		/// <param name="targetSquareIndex"></param>
		/// <returns></returns>
		private int GetGreaterDistance(int currentSquareIndex, int targetSquareIndex)
		{
			return Math.Max(FileDistance(currentSquareIndex,targetSquareIndex),
				RankDistance(currentSquareIndex,targetSquareIndex));

		}

		// -- GROUP END --

		// GROUP: Chesspiece Move/Capture Validation and Analysis Methods
		/// <summary>
		/// Verifies if the requested move is legal, ie according to the rules of chess.
		/// </summary>
		/// <param name="fromSquare">Integer 0-63 representing square piece is moving FROM</param>
		/// <param name="toSquare">Integer 0-63 representing square piece is being moved TO</param>
		/// <returns>TRUE if the piece move from fromSquare to toSquare is legitimate.</returns>
		private bool IsMoveLegit(int fromSquare, int toSquare)
		{
			// Check that the arguments are in-bounds
			if(fromSquare < 0 || fromSquare > 63)
			{
				throw new ArgumentException("FROM square is out of range: " + fromSquare.ToString());
			}
			else if(toSquare < 0 || toSquare > 63)
			{
				throw new ArgumentException("TO square is out of range: " + toSquare.ToString());
			}
			
			BitBoard fromBitBoard = _bitMask[fromSquare];
			BitBoard toBitBoard = _bitMask[toSquare];
			
			// You can't take out your own men!
			if(MoveOnFriendlies(fromSquare,toSquare))
				return false;

			// Validate piece-specific moves/captures
			switch(Math.Abs(GetPiece(fromSquare)))
			{
				case PAWN:
					return CheckPawnMove(fromSquare,toSquare);

				case KNIGHT:
					if((_KnightAttacks[fromSquare] & toBitBoard) == 0)
						return false;
					break;

				case BISHOP:
					return CheckBishopMove(fromSquare,toSquare);

				case ROOK:
					return CheckRookMove(fromSquare,toSquare);

				case QUEEN:
					return ( (CheckBishopMove(fromSquare,toSquare) || CheckRookMove(fromSquare,toSquare)));

				case KING:
					return CheckKingMove(fromSquare,toSquare);
			}

			return true;
		}

		/// <summary>
		/// Determines if a castling move is valid.
		/// </summary>
		/// <param name="fromSquare">King square.</param>
		/// <param name="toSquare">Destination square.</param>
		/// <param name="sideToEvaluate">Side color to evaluate.</param>
		/// <returns>TRUE if castling is legal, FALSE otherwise.</returns>
		private bool IsCastleLegit(int fromSquare, int toSquare, PlayerTurn sideToEvaluate)
		{
			// This method assumes that the prelim checks have already been made with respect to
			// prior movements of either the king or rooks;
			// In order for castling to be legal, several criteria need to be satisfied:
			// A) king is not under check
			// B) destination square for king is unoccupied
			// C) destination square for rook is unoccupied
			// D) no pieces between king and rook
			// E) king does not "move" through squares "attacked" by opponent
			// F) king is not in check after castling
			// --> CheckCastlingSquares() addresses B) to F)
			
			if((sideToEvaluate==PlayerTurn.White && _chessPosition.whiteKingCheck==true) ||
				(sideToEvaluate==PlayerTurn.Black && _chessPosition.blackKingCheck==true))
			{
				return false;
			}

			if(sideToEvaluate==PlayerTurn.White && _chessPosition.whiteKingMoved==false)
			{
				// white king-side
				if((fromSquare==WHITE_KING_SQUARE && toSquare==WHITE_KINGSIDE_CASTLE_TO) &&
					_chessPosition.whiteRRookMoved==false)
				{
					if(!CheckCastlingSquares(WHITE_RCASTLE_SQ,sideToEvaluate))
					{
						return false;
					}
					else
					{
						return true;
					}
				}

				// white queen-side
				if((fromSquare==WHITE_KING_SQUARE && toSquare==WHITE_QUEENSIDE_CASTLE_TO) &&
					_chessPosition.whiteLRookMoved==false)
				{
					if(!CheckCastlingSquares(WHITE_LCASTLE_SQ,sideToEvaluate))
					{
						return false;
					}
					else
					{
						return true;
					}
				}
			}
			else if(sideToEvaluate==PlayerTurn.Black && _chessPosition.blackKingMoved==false)
			{
				// black king-side
				if((fromSquare==BLACK_KING_SQUARE && toSquare==BLACK_KINGSIDE_CASTLE_TO) &&
					_chessPosition.blackRRookMoved==false)
				{
					if(!CheckCastlingSquares(BLACK_RCASTLE_SQ,sideToEvaluate))
					{
						return false;
					}
					else
					{
						return true;
					}
				}

				// black queen-side
				if((fromSquare==BLACK_KING_SQUARE && toSquare==BLACK_QUEENSIDE_CASTLE_TO) &&
					_chessPosition.blackLRookMoved==false)
				{
					if(!CheckCastlingSquares(BLACK_LCASTLE_SQ,sideToEvaluate))
					{
						return false;
					}
					else
					{
						return true;
					}
				}
			}

			return false;
		}
		
		/// <summary>
		/// Determines if a castling move is being made.
		/// </summary>
		/// <param name="fromSquare">King square.</param>
		/// <param name="toSquare">Post-move king square.</param>
		/// <returns>TRUE if the piece is a king and is following the king or queen-side movement patterns.</returns>
		private bool IsCastlingMove(int fromSquare, int toSquare)
		{
			if(GetPiece(fromSquare) != KING && GetPiece(fromSquare) != -KING)
			{
				return false;
			}

			if((fromSquare==WHITE_KING_SQUARE && toSquare==WHITE_KINGSIDE_CASTLE_TO) ||
				(fromSquare==WHITE_KING_SQUARE && toSquare==WHITE_QUEENSIDE_CASTLE_TO) ||
				(fromSquare==BLACK_KING_SQUARE && toSquare==BLACK_KINGSIDE_CASTLE_TO) ||
				(fromSquare==BLACK_KING_SQUARE && toSquare==BLACK_QUEENSIDE_CASTLE_TO))
			{
				return true;
			}

			return false;
		}

		/// <summary>
		/// Verifies whether the provided castling squares are unoccupied and not
		/// under threat by opposing pieces.
		/// </summary>
		/// <param name="castlingSquares">Array of castling squares to check.</param>
		/// <param name="sideToEvaluate">Player that is castling.</param>
		/// <returns>TRUE if squares are unoccupied and not threatened.</returns>
		private bool CheckCastlingSquares(int[] castlingSquares, PlayerTurn sideToEvaluate)
		{
			if(castlingSquares.GetLength(0) < 2 || castlingSquares.GetLength(0) > 3)
			{
				throw new ArgumentException("The array of squares to evaluate for castling is not correctly dimensioned.");
			}

			// Are all the squares clear?
			foreach(int sq in castlingSquares)
			{
				if(GetPiece(sq) != NONE)
				{
					return false;
				}
			}

			// Are all the squares the king must pass through free of threat?
			// We only need to check the first two of the queenside squares, and the only two of the kingside squares
			for(int x=0; x<2; x++)
			{
				if(IsSquareAttacked(sideToEvaluate,castlingSquares[x]))
				{
					return false;
				}
			}

			return true;
		}
		
		/// <summary>
		/// Checks if a given move is a pawn moving to its last rank, resulting in a promotion. 
		/// </summary>
		/// <param name="fromSquare">Index (0-63) of the pawn start square.</param>
		/// <param name="toSquare">Index (0-63) of the pawn destination square.</param>
		/// <returns>TRUE if pawn move results in a promotion.</returns>
		private bool IsPawnPromotion(int fromSquare, int toSquare)
		{
			Piece pawn = GetPiece(fromSquare);
			if(pawn != PAWN && pawn != -PAWN)
			{
				return false;
			}
			
			switch(pawn)
			{
				case PAWN:
					if(toSquare >= 0 && toSquare <= 7)
					{
						return true;
					}
					else
					{
						return false;
					}
			
				case -PAWN:
					if(toSquare >= 56 && toSquare <= 63)
					{
						return true;
					}
					else
					{
						return false;
					}
			}

			// if we get here, there has to be a problem
			return false;
		}

		/// <summary>
		/// Verifies that the proposed king move or capture is valid for the provided from and to squares.
		/// </summary>
		/// <param name="fromSquare">Square index (0-63) piece is moving FROM.</param>
		/// <param name="toSquare">Square index (0-63) piece is moving TO.</param>
		/// <returns>TRUE if move is valid.</returns>
		/// <remarks>This method also verifies castling maneuvers.</remarks>
		private bool CheckKingMove(int fromSquare, int toSquare)
		{
			PlayerTurn kingSide = GetPieceColor(fromSquare);
			BitBoard toBitBoard = _bitMask[toSquare];
			
			// Is this a castling maneuver? -- Verify legality
			if(IsCastlingMove(fromSquare,toSquare))
			{
				return IsCastleLegit(fromSquare,toSquare,kingSide);
			}

			// Verify usual moves/attacks
			if((_KingAttacks[fromSquare] & toBitBoard)==0)
			{
				return false;
			}

			return true;
		}

		/// <summary>
		/// Verifies that the proposed pawn move or capture is valid for the provided from and to squares.
		/// </summary>
		/// <param name="fromSquare">Square index (0-63) piece is moving FROM</param>
		/// <param name="toSquare">Square index (0-63) piece is moving TO</param>
		/// <returns>TRUE if valid</returns>
		private bool CheckPawnMove(int fromSquare, int toSquare)
		{
			BitBoard toBitBoard = _bitMask[toSquare];
			PlayerTurn pieceColor = GetPieceColor(fromSquare);

			// Move
			switch(GetPiece(toSquare))
			{
				case NONE:
					// Valid Move?
					if(pieceColor==PlayerTurn.White)
					{
						if((_wPawnMoves[fromSquare] & toBitBoard) == 0)
						{
							if(IsEnPassantLegit(fromSquare,toSquare))
							{
								_chessPosition.enPassantAvailable = true;
								return true;
							}
							else
							{
								return false;
							}
						}
						else
						{
							return true;
						}
					}
					else if(pieceColor==PlayerTurn.Black)
					{
						if((_bPawnMoves[fromSquare] & toBitBoard) == 0)
						{
							if(IsEnPassantLegit(fromSquare,toSquare))
							{
								_chessPosition.enPassantAvailable = true;
								return true;
							}
							else
							{
								return false;
							}
						}
						else
						{
							return true;
						}
					}	
					break;

				default:
					// Valid Capture? -- Check for en passant captures
					if(pieceColor==PlayerTurn.White)
					{
						if((_wPawnAttacks[fromSquare] & toBitBoard) == 0)
						{
							return false;
						}
						else
						{
							return true;
						}
					}
					else if(pieceColor==PlayerTurn.Black)
					{
						if((_bPawnAttacks[fromSquare] & toBitBoard) == 0)
						{
							return false;
						}
						else
						{
							return true;
						}
					}
					break;
			}

			// If we reach this point, err on side of caution and invalidate the move
			return false;
		}

		/// <summary>
		/// Determines if an attempted en passant capture is valid.
		/// </summary>
		/// <param name="fromSquare">Index (0-63) of from square.</param>
		/// <param name="toSquare">Index (0-63) of to square.</param>
		/// <returns>TRUE if the conditions for an en passant capture are met.</returns>
		/// <remarks>
		/// En passant captures are unique moves that require specific preconditions.  This method
		/// determines if the following criteria have been met for a proposed en passant capture:
		/// <list type="">
		/// <item>Verify a pawn is being moved and that the destination square is empty.</item>
		/// <item>The attacked square is within the range of the attacking pawn.</item>
		/// <item>The attacking pawn is striking from its fifth rank.</item>
		/// <item>The previous move must be an opposing pawn moving into its fourth rank.</item>
		/// </list>
		/// </remarks>
		private bool IsEnPassantLegit(int fromSquare, int toSquare)
		{
			// Verify we have a pawn moving and that the destination square is empty
			Piece pawnToMove = GetPiece(fromSquare);
			Piece toSquareContains = GetPiece(toSquare);
			if(pawnToMove!=PAWN && pawnToMove!=-PAWN) return false;
			if(toSquareContains!=NONE) return false;
			PlayerTurn sideToEval = GetPieceColor(fromSquare);

			// Is it attacking a valid square
			if((sideToEval==PlayerTurn.Black && (_bPawnAttacks[fromSquare] & _bitMask[toSquare])==0) ||
				(sideToEval==PlayerTurn.White && (_wPawnAttacks[fromSquare] & _bitMask[toSquare])==0)) return false;

			// Is this pawn in its fifth rank?
			BitBoard fromBitBoard = _bitMask[fromSquare];
			if(sideToEval==PlayerTurn.White)
			{
				if((_whiteFifthRankBitMask & fromBitBoard)==0) return false;
			}
			else
			{
				if((_blackFifthRankBitMask & fromBitBoard)==0) return false;
			}

			// Get the last move made and ensure a pawn was moved...
			MoveHistoryItem lastMove = GetLastMoveItem();
			if(lastMove.movedPiece!=PAWN && lastMove.movedPiece!=-PAWN) return false;

			// The previous move must be a double-step pawn move (ie to fourth rank)
			if(Math.Abs(lastMove.fromSquare - lastMove.toSquare) != 16) return false;

			// And we need to ensure that we are indeed passing a reachable pawn
			if(sideToEval==PlayerTurn.White)
			{
				if(((_chessPosition.blackPawns & _squarePlus_8[toSquare]) != 0) && GetPiece(toSquare+8) != -PAWN) return false;
			}
			else
			{
				if(((_chessPosition.whitePawns & _squareMinus_8[toSquare]) != 0) && GetPiece(toSquare-8) != PAWN) return false;
			}

			return true;
		}

		/// <summary>
		/// Is the toSquare occupied by a friendly piece?
		/// </summary>
		/// <param name="fromSquare">Piece that is attempting an attack.</param>
		/// <param name="toSquare">Target square of the attack.</param>
		/// <returns>True if toSquare is occupied by a friendly piece.</returns>
		private bool MoveOnFriendlies(int fromSquare, int toSquare)
		{
			if(fromSquare < 0 || fromSquare > 63 || toSquare < 0 || toSquare > 63)
			{
				throw new ArgumentException("fromSquare and toSquare must be values between 0-63.");
			}
			
			// Ensure that we're actually moving a piece.
			Piece fromPiece = GetPiece(fromSquare);

			// Determine the friendly pieces on the board
			BitBoard friendlies = new BitBoard();
			BitBoard target = _bitMask[toSquare];
			if(fromPiece > 0)	// White pieces are positive values, Black are negative
			{
				friendlies = _chessPosition.whitePieces;
			}
			else
			{
				friendlies = _chessPosition.blackPieces;
			}

			// if the toSquare is occupied by a bit AND the
			// friendlies bit for that square is also occupied,
			// we'll get a non-zero result -- ILLEGAL MOVE
			if((target & friendlies) != 0)
			{
				return true;
			}
			
			return false;
		}

		/// <summary>
		/// Validates a diagonal target square for a pawn capture, ensuring the target is on the
		/// board and complies with the rules of chess.
		/// </summary>
		/// <param name="currentSquareIndex">Index (0-63) that a pawn is moving FROM.</param>
		/// <param name="targetSquareIndex">Index (0-63) that a pawn is moving TOWARD.</param>
		/// <returns>TRUE if the move represents a valid pawn capture.</returns>
		private bool ValidPawnCapture(int currentSquareIndex, int targetSquareIndex)
		{
			if(FileDistance(currentSquareIndex,targetSquareIndex)==1 &&
				RankDistance(currentSquareIndex,targetSquareIndex)==1 &&
				(targetSquareIndex<64) && (targetSquareIndex>-1))
			{
				return true;
			}
			return false;
		}


		/// <summary>
		/// Validates a pawn's first move where it can move forward 1 or 2 squares.
		/// </summary>
		/// <param name="currentSquareIndex">Index (0-63) that a pawn is moving FROM.</param>
		/// <param name="targetSquareIndex">Index (0-63) that a pawn is moving TOWARD.</param>
		/// <returns>TRUE if the move corresponds to a valid first move for a pawn.</returns>
		private bool ValidPawnFirstMove(int currentSquareIndex, int targetSquareIndex)
		{
			if(FileDistance(currentSquareIndex,targetSquareIndex) <= 2 &&
				RankDistance(currentSquareIndex,targetSquareIndex) == 0 &&
				(targetSquareIndex<64) && (targetSquareIndex>-1))
			{
				return true;
			}
			return false;
		}

		
		/// <summary>
		/// Validates a pawn's subsequent moves where it may only advance 1 square per turn.
		/// </summary>
		/// <param name="currentSquareIndex">Index (0-63) that pawn is moving FROM.</param>
		/// <param name="targetSquareIndex">Index (0-63) that pawn is moving TOWARD.</param>
		/// <returns>TRUE if the move corresponds to a valid pawn move.</returns>
		private bool ValidPawnMove(int currentSquareIndex, int targetSquareIndex)
		{
			if(FileDistance(currentSquareIndex,targetSquareIndex)==1 &&
				RankDistance(currentSquareIndex,targetSquareIndex)==0 &&
				(targetSquareIndex<64) && (targetSquareIndex>-1))
			{
				return true;
			}
			return false;
		}	

		/// <summary>
		/// Validates a target square for a knight capture (1,2 & 1 across)
		/// </summary>
		/// <param name="currentSquareIndex">Index (0-63) of square knight is to move from.</param>
		/// <param name="targetSquareIndex">Index (0-63) of square knight is moving toward.</param>
		/// <returns>TRUE if the target square is in the allowable range for the knight.</returns>
		private bool ValidKnightCapture(int currentSquareIndex, int targetSquareIndex)
		{
			if(FileDistance(currentSquareIndex,targetSquareIndex) > 2 ||
				RankDistance(currentSquareIndex,targetSquareIndex) > 2)
			{
				return false;
			}
			return true;
		}


		/// <summary>
		/// Validates a queen or bishop move along a diagonal.
		/// </summary>
		/// <param name="currentSquareIndex">Index (0-63) of the square the bishop or queen is moving FROM.</param>
		/// <param name="targetSquareIndex">Index (0-63) of the square the bishop or queen is moving TOWARD.</param>
		/// <returns>TRUE if the move corresponds to a move along a diagonal from the given square.</returns>
		private bool ValidBishopQueenMove(int currentSquareIndex, int targetSquareIndex)
		{
			if(FileDistance(currentSquareIndex,targetSquareIndex) == 1 &&
				RankDistance(currentSquareIndex,targetSquareIndex) == 1 &&
				(targetSquareIndex < 64) && (targetSquareIndex >= 0 ))
			{
				return true;
			}
			return false;
		}


		/// <summary>
		/// Validates a queen or rook move along unoccupied ranks or files
		/// </summary>
		/// <param name="currentSquareIndex">Index (0-63) of the square the rook or queen is moving FROM.</param>
		/// <param name="targetSquareIndex">Index (0-63) of the square the rook or queen is moving TOWARD.</param>
		/// <returns>TRUE if the move corresponds to a move along a rank or file from the given square.</returns>
		private bool ValidRookQueenMove(int currentSquareIndex, int targetSquareIndex)
		{
			int rankDist = FileDistance(targetSquareIndex,currentSquareIndex);
			int fileDist = RankDistance(targetSquareIndex,currentSquareIndex);

			if( (((rankDist>=1) && (fileDist==0)) ||
				((rankDist==0) && (fileDist>=1))) &&
				(targetSquareIndex < 64) && (targetSquareIndex >= 0)
				)
			{
				return true;
			}
			return false;
		}
		// -- GROUP END --

		// GROUP: Check and Mate Evaluation Methods
		/// <summary>
		/// Analyzes a committed move from MakeMove() to determine if it places the player's king in check,
		/// or the opponent's king in check or mate.
		/// </summary>
		/// <param name="playerMoveResult">PlayerMoveResult object containing details for the move.</param>
		private void AnalyzeForCheckAndMate(ref PlayerMoveResult playerMoveResult)
		{
			playerMoveResult.PlayerMoveStatus = MoveResult.LEGAL;

			// Does this move put the player's king in check? 
			if(EvaluateForCheck(PlayerToMove))
			{
				RetractLastMove();
				playerMoveResult.PlayerMoveStatus = MoveResult.ILLEGAL;
				return;
			}

			// Is the player's king currently in check?  If so, does this move remove the check?
			if((PlayerToMove==PlayerTurn.Black && _chessPosition.blackKingCheck==true) ||
				(PlayerToMove==PlayerTurn.White && _chessPosition.whiteKingCheck==true))
			{
				if(EvaluateForCheck(PlayerToMove)) // TRUE==king still in check
				{
					RetractLastMove();
					playerMoveResult.PlayerMoveStatus = MoveResult.ILLEGAL;
					playerMoveResult.PlayerMoveType = MoveType.ILLEGAL;
					return;
				}
				else							   // FALSE==king removed from check
				{
					if(PlayerToMove==PlayerTurn.Black)
					{
						_chessPosition.blackKingCheck = false;
					}
					else
					{
						_chessPosition.whiteKingCheck = false;
					}
					playerMoveResult.PlayerMoveStatus = MoveResult.LEGAL;
					return;
				}
			}
			
			// Analyze board for CHECK and MATE
			if(EvaluateForCheck(PlayerToMove==PlayerTurn.Black ? PlayerTurn.White : PlayerTurn.Black))
			{
				if(PlayerToMove==PlayerTurn.Black)
				{
					_chessPosition.whiteKingCheck = true;
					MoveHistoryItem mhi = GetLastMoveItem();
					mhi.whiteKingCheck = true;
					_MoveHistory[_MoveHistory.Count-1] = mhi;
					
					Debug.WriteLine("!! WHITE KING IS IN CHECK !!");
				}
				else if(PlayerToMove==PlayerTurn.White)
				{
					_chessPosition.blackKingCheck = true;
					MoveHistoryItem mhi = GetLastMoveItem();
					mhi.blackKingCheck = true;
					_MoveHistory[_MoveHistory.Count-1] = mhi;

					Debug.WriteLine("!! BLACK KING IS IN CHECK !!");
				}
				
				// Does this move put the opposing king in CHECKMATE?
				if(_chessPosition.blackKingCheck==true || _chessPosition.whiteKingCheck==true)
				{
					// Does the opposing king have at least one avenue to avoid MATE?
					if(ExtricateFromCheck(PlayerToMove==PlayerTurn.Black ? PlayerTurn.White : PlayerTurn.Black))
					{
						playerMoveResult.PlayerMoveStatus = MoveResult.CHECK;
					}
					else
					{
						_isMate = true;
						playerMoveResult.PlayerMoveStatus = MoveResult.MATE;
						Debug.WriteLine("!! KING IS MATED !!");
					}
				}
			}
		}

		/// <summary>
		/// Analyze the current board layout for check against a given side.
		/// </summary>
		/// <param name="sideToEval">King side to evaluate for check.</param>
		/// <returns>TRUE if the provided king is in check</returns>
		private bool EvaluateForCheck(PlayerTurn sideToEval)
		{
			int kingSquare = (sideToEval == PlayerTurn.Black ? _chessPosition.blackKingSquare : _chessPosition.whiteKingSquare);
			return IsSquareAttacked(sideToEval,kingSquare);			
		}

		/// <summary>
		/// Determines if the side currently in check can be extricated.
		/// </summary>
		/// <returns>TRUE if side can be extricated, FALSE if not, ie MATE</returns>
		private bool ExtricateFromCheck(PlayerTurn sideToEvaluate)
		{
			// Three tests for extrication:
			// 1) Can a friendly piece INTERCEPT the attack?
			// 2) Can the attacking piece be CAPTURED?
			// 3) Can the king EVADE attack to a safe square?
			// If ALL of these tests evaluate to FALSE then the player queried is MATED.
			MoveHistoryItem lastMove = GetLastMoveItem();
			bool extricateFlag = false;
			bool interceptFlag = false;
			bool captureFlag = false;
			bool evadeFlag = false;

			// TEST 1:	INTERCEPT
			// --> Determine if any pieces can "attack" any of the squares between the
			//	   king and the attacking piece;  this would indicate that a successful
			//	   intercept can be made, therefore avoid MATE.
			//	   -->  An intercept can be made by any piece, but only attacks involving
			//			a ROOK, BISHOP or QUEEN can be intercepted.
			if(InterceptAttack(sideToEvaluate))
			{
				interceptFlag = true;
			}

			// TEST 2:  CAPTURE
			// -->  Determine if the attacking piece can be captured.
			//		-->  If at least one allied piece can take out the attacker, the CAPTURE
			//			 test is satisfied and mate can be avoided.
			//		-->  WRINKLE:  We must make sure that by making the capture, we aren't
			//			 opening the king up to a revealed check.
			if(CaptureAttacker(sideToEvaluate))
			{
				captureFlag = true;
			}

			// TEST 3:  EVADE
			// -->	Determine if the defending king can evade attack to safe haven.
			//		-->  For each of the unoccupied surrounding squares, test to ensure
			//			 the square isn't under "attack".
			if(EvadeAttacker(sideToEvaluate))
			{
				evadeFlag = true;
			}

			// If any of the extrication tests are TRUE, mate has been avoided.
			extricateFlag = interceptFlag | captureFlag | evadeFlag;
			return extricateFlag;
		}

		/// <summary>
		/// Determine if the defending king can evade attack by moving to an available surrounding square.
		/// </summary>
		/// <param name="sideToEvaluate">Defending king under attack.</param>
		/// <returns>TRUE if the defending king can escape to one or more surrounding squares.</returns>
		private bool EvadeAttacker(PlayerTurn sideToEvaluate)
		{
			int kingSquare = sideToEvaluate == PlayerTurn.Black ? _chessPosition.blackKingSquare :
				_chessPosition.whiteKingSquare;
			ArrayList kingAttackIndices = GetSquareIndices(_KingAttacks[kingSquare]);
			foreach(int squareIndex in kingAttackIndices)
			{
				// In future revisions, we'll store the available squares in a collection
				if(IsMoveLegit(kingSquare,squareIndex))
				{
					// Does this legit move compromise the king?
					if(!IsKingCompromised(kingSquare,squareIndex,sideToEvaluate))
					{
						return true;
					}
				}
			}
			return false;
		}

		/// <summary>
		/// Determine if the piece attacking the defending king can be captured.
		/// </summary>
		/// <param name="sideToEvaluate">Defending king under attack.</param>
		/// <returns>TRUE if the attacking piece can be captured by a defending piece.</returns>
		private bool CaptureAttacker(PlayerTurn sideToEvaluate)
		{
			// The procedure here is twofold:
			// First, can the the attacking piece be captured by a defending piece?
			// If yes, does capturing that piece with a given defending piece open the
			// defending king up to a revealed check?
			// --> We can check for this by "removing" the capturing piece from the board and 
			//	   determining if the king is in check.
			ArrayList attackingPiece = new ArrayList();
			int kingSquare = sideToEvaluate == PlayerTurn.Black ? _chessPosition.blackKingSquare :
				_chessPosition.whiteKingSquare;

			FindAttackingPieces(ref attackingPiece, kingSquare, sideToEvaluate);

			BitBoard alliedPiecesBB = sideToEvaluate==PlayerTurn.Black ? _chessPosition.blackPieces : _chessPosition.whitePieces;
			BitBoard axisPiecesBB = sideToEvaluate==PlayerTurn.Black ? _chessPosition.whitePieces : _chessPosition.blackPieces;
			ArrayList alliedPieceIndices = GetSquareIndices(alliedPiecesBB);
			
			// Iterate through defending pieces to determine if any can mount a legitimate
			// attack on the the opponent's piece that is attacking the defending king.
			foreach(int allyPieceIndex in alliedPieceIndices)
			{
				if(IsMoveLegit(allyPieceIndex,(int)attackingPiece[0]))
				{
					// Does this capture compromise the defending king?
					// Return TRUE on the first move we find that won't compromise the king.
					if(! IsKingCompromised(allyPieceIndex,(int)attackingPiece[0],sideToEvaluate))
					{
						return true;
					}
				}
			}
			return false;
		}
		/// <summary>
		/// Determines if a check attack on a king piece can be intercepted by an allied piece, thus negating the attack.
		/// </summary>
		/// <remarks>This function is used as one of several tests to determine if a king has been MATED.
		/// Intercepts can only be performed against attacks by Bishops, Queens and Rooks, since they can attack
		/// from a distance.  Pawns, knights and kings need to be proximate to the defending king to attack.
		/// Note that if there are no available intercept squares between the attacker and defender squares, FALSE 
		/// will be automatically returned.</remarks>
		/// <param name="sideToEvaluate">The king side to test.</param>
		/// <returns>TRUE if check can be intercepted by another piece, FALSE otherwise.</returns>
		private bool InterceptAttack(PlayerTurn sideToEvaluate)
		{
			if(_chessPosition.blackKingCheck==false && _chessPosition.whiteKingCheck==false)
			{
				throw new ApplicationException("Intercept test can only be performed when a king is under CHECK.");
			}
			
			// Get the recorded last move object and set-up for fetching the king square
			MoveHistoryItem lastMove = (MoveHistoryItem)_MoveHistory[_MoveHistory.Count - 1];
			int kingSquare = sideToEvaluate == PlayerTurn.Black ? _chessPosition.blackKingSquare :
				_chessPosition.whiteKingSquare;

			// Get the attacking pieces for the king square
			// NB:  We can have up to two pieces attacking the square-- a classic forked attack.
			// The only way out is for the king to remove one of the forking attackers without landing in check.
			ArrayList attackingPieceSquares = new ArrayList();
			FindAttackingPieces(ref attackingPieceSquares,kingSquare,sideToEvaluate);
			if(attackingPieceSquares.Count == 0)
			{
				return false; // If no attacking pieces, no intercept
			}
			else if(attackingPieceSquares.Count > 2)
			{
				//TODO: Throw a ChessRulesEngineException here.
				throw new ChessRulesEngineException("Error:  Too many pieces found attacking the king while computing intercept attacks.\n" +
					"There should be at most only two pieces attacking a king after a given move by an attacker.");
			}
			
			// Iterate through collection of attacking piece squares, doing intercept
			// analysis for Rooks, Queens and Bishops
			foreach(int squareIndex in attackingPieceSquares)
			{
				Piece pieceType = Math.Abs(GetPiece(squareIndex));
				if(pieceType==ROOK || pieceType==QUEEN || pieceType==BISHOP)
				{
					// Get a collection of the candidate attack interception squares between the king and the attacking piece;
					// Iterate through the collection and determine if any of the squares can be attacked.
					ArrayList interceptSquares = GetInterceptSquares(squareIndex,kingSquare);

					// Here, we are getting the indices for all the pieces for the allied side-- i.e. if we're evaluating for a black king,
					// we want all the black pieces.  Note that we are excluding the king bit from the pieces bitboard since we only want to
					// know if any of the other pieces can attack the intercept set.
					BitBoard alliedPiecesBB = sideToEvaluate==PlayerTurn.Black ? (_chessPosition.blackPieces ^ _bitMask[_chessPosition.blackKingSquare]) :
						(_chessPosition.whitePieces ^ _bitMask[_chessPosition.whiteKingSquare]);
					ArrayList alliedPieceIndices = GetSquareIndices(alliedPiecesBB);
					foreach(int square in interceptSquares)
					{
						foreach(int allyIndex in alliedPieceIndices)
						{
							// For now, we return true if even one piece can make a successful attack on a single square to disrupt
							// the attack.  In future versions, we'll collect the pieces and indices to provide the player with
							// a list of pieces that are attacking the intercept squares.
							// Successful intercept move must not only be possible, but also not put the defending king in check.
							if(IsMoveLegit(allyIndex,square))
							{
								if(!IsKingCompromised(allyIndex,square,sideToEvaluate))
								{
									return true;
								}
							}
						}
					}
				}
			}
			return false;
		}

		/// <summary>
		/// Returns an ArrayList of square indexes (0-63) that separate an attacking square and defending square.
		/// </summary>
		/// <param name="attackerSquare">Index of square occupied by attacking piece (0-63)</param>
		/// <param name="defenderSquare">Index of square occupied by defending piece (0-63)</param>
		/// <returns>ArrayList of squares separating the attacker and defender.  If no squares separate them, an
		/// empty array is returned.
		/// </returns>
		private ArrayList GetInterceptSquares(int attackerSquare, int defenderSquare)
		{
			if(attackerSquare < 0 || attackerSquare > 63 || defenderSquare < 0 || defenderSquare > 63)
			{
				throw new ArgumentException("Attacker square and target square must be within the range 0-63.");
			}
			else if(attackerSquare==defenderSquare)
			{
				throw new ArgumentException("Attacker square and target square cannot refer to the same location on the board.");
			}
			
			BitBoard[] emptyBitBoardArray = new BitBoard[] {};
			BitBoard attackSideBB = 0;
			BitBoard defendSideBB = 0;
			BitBoard resultBB = 0;
			const int WE_DIAGONAL = 9;
			const int EW_DIAGONAL = 7;
			const int NS_VERTICAL = 8;

			int rawDistance = Math.Abs(attackerSquare - defenderSquare);
			// We can only get intervening squares if they exist
			if(rawDistance == 0)
			{
				return new ArrayList();
			}
			int rankDistance = RankDistance(attackerSquare,defenderSquare);	// A-H
			int fileDistance = FileDistance(attackerSquare,defenderSquare); // 1-8
			
			switch((attackerSquare > defenderSquare))
			{
				case true:
					if((rawDistance % WE_DIAGONAL) == 0)	// West to East diagonal squares
					{
						defendSideBB = _squarePlus_9[defenderSquare];
						attackSideBB = _squareMinus_9[attackerSquare];
					}
					else if((rawDistance % NS_VERTICAL) == 0)	// North to south vertical squares
					{
						defendSideBB = _squarePlus_8[defenderSquare];
						attackSideBB = _squareMinus_8[attackerSquare];
					}
					else if(((rawDistance % EW_DIAGONAL) == 0) && fileDistance > 0 )	// East to west diagonal squares
					{
						defendSideBB = _squarePlus_7[defenderSquare];
						attackSideBB = _squareMinus_7[attackerSquare];
					}
					else if(fileDistance==0)	// Horizontal squares -- attacker on east side, defender on west
					{
						defendSideBB = _squarePlus_1[defenderSquare];
						attackSideBB = _squareMinus_1[attackerSquare];
					}
					break;

				case false:
					if((rawDistance % WE_DIAGONAL) == 0)	// West to east diagonal squares
					{
						defendSideBB = _squareMinus_9[defenderSquare];
						attackSideBB = _squarePlus_9[attackerSquare];
					}
					else if((rawDistance % NS_VERTICAL) == 0)	// North to south vertical squares
					{
						defendSideBB = _squareMinus_8[defenderSquare];
						attackSideBB = _squarePlus_8[attackerSquare];
					}
					else if(((rawDistance % EW_DIAGONAL) == 0) && fileDistance > 0)	// East to west diagonal squares
					{
						defendSideBB = _squareMinus_7[defenderSquare];
						attackSideBB = _squarePlus_7[attackerSquare];
					}
					else if(fileDistance==0)	// Horizontal squares -- attacker on west side, defender on east
					{
						defendSideBB = _squareMinus_1[defenderSquare];
						attackSideBB = _squarePlus_1[attackerSquare];
					}
					break;
			}
			
			// Combine the defender and attacker intervening square bitboards to
			// get the common squares between them.
			resultBB = defendSideBB & attackSideBB;
			
			return GetSquareIndices(resultBB);
		}

		/// <summary>
		/// Test a move to determine if it will place a player's king in check.
		/// </summary>
		/// <param name="moveFrom">Square to move piece from.</param>
		/// <param name="moveTo">Square to move piece to.</param>
		/// <param name="sideToEvaluate">Defending king side.</param>
		/// <returns>TRUE if the defending king will be placed in check because of the move.</returns>
		private bool IsKingCompromised(int moveFrom, int moveTo, PlayerTurn sideToEvaluate)
		{
			if(moveFrom < 0 || moveFrom > 63)
			{
				throw new ArgumentException("moveFrom index is out of range: " + moveFrom.ToString());
			}
			if(moveTo < 0 || moveTo > 63)
			{
				throw new ArgumentException("moveTo index is out of range: " + moveTo.ToString());
			}	

			// Procedure:
			// a) Assume move is legitimate -- commit the move to the board
			// b) Call EvaluateForCheck()
			//    |-> TRUE:		King is in check from move -- undo the move, return TRUE.
			//	  |-> FALSE:	King is not in check from move -- undo the move, return FALSE.
			DoPlayerMove(moveFrom,moveTo);
			bool isKingCompromised = EvaluateForCheck(sideToEvaluate);
			RetractLastMove();
			return isKingCompromised;
		}

		/// <summary>
		/// Analyzes board for attacks against a given square.
		/// </summary>
		/// <param name="sideToEval">Player side to evaluate attacks against.</param>
		/// <param name="attackedSquare">Index of square under attack (0-63)</param>
		/// <returns>TRUE if the square for the side being evaluated is under attack
		/// by one or more pieces.
		/// </returns>
		private bool IsSquareAttacked(PlayerTurn sideToEval, int attackedSquare)
		{
			// Use the "superpiece" algorithm to test for attacks against a given square by superimposing
			// each of the piece types in the attacked square and determining if a valid attack can be made to any
			// opposing piece in range of that piece type

			bool pieceIsAttacked = false;
			ArrayList attackingPieces = new ArrayList();
			FindAttackingPieces(ref attackingPieces,attackedSquare,sideToEval);
		
			// Crude, but effective;
			// If we have one or more pieces attacking attackedSquare, we return TRUE.
			pieceIsAttacked = attackingPieces.Count > 0 ? true : false;
			return pieceIsAttacked;
		}

		/// <summary>
		/// Iterates through pieces attacking a given square, collecting them in an referenced arraylist.
		/// </summary>
		/// <param name="attackingPieceIndices">ArrayList of the indices (0-63) of attacking pieces to build.</param>
		/// <param name="attackedSquare">Attacked square to evaluate for attack.</param>
		/// <param name="sideToEval">Player side to find attacking pieces against.</param>
		private void FindAttackingPieces(ref ArrayList attackingPieceIndices, int attackedSquare, PlayerTurn sideToEval)
		{
			if(attackedSquare < 0 || attackedSquare > 63)
			{
				throw new ArgumentException("Attacked square must be between 0-63.");
			}
			
			// Get the indices for all the chess pieces (king inclusive) for the attacking side
			ArrayList attackingPieces = new ArrayList();
			attackingPieces = GetSquareIndices((sideToEval==PlayerTurn.White ? _chessPosition.blackPieces : _chessPosition.whitePieces));
			attackingPieces.Add(sideToEval==PlayerTurn.White ? _chessPosition.blackKingSquare : _chessPosition.whiteKingSquare);

			// Set up a "phantom piece" in the attacked square for calculating attacks against-- this is done to satisfy
			// pawn attacks using the IsMoveLegit() method by providing a legit target while testing for valid attack moves.
			bool phantomOn = false;
			if(_virtualBoard[attackedSquare] == NONE)
			{
				_virtualBoard[attackedSquare] = (sideToEval==PlayerTurn.Black ? PAWN : -PAWN);
				phantomOn = true;
			}
		
			// Iterate through the attacking candidate pieces for successful attacks
			foreach(int index in attackingPieces)
			{				
				if(IsMoveLegit(index,attackedSquare))
				{
					attackingPieceIndices.Add(index);
				}
			}
			
			// Remove the "phantom" if necessary
			if(phantomOn)
			{
				_virtualBoard[attackedSquare] = NONE;
			}
		}
		// -- GROUP END --

		// GROUP: Make Move and Retract Move Methods
		/// <summary>
		/// Enters a move for validation and recording by the rules engine.
		/// </summary>
		/// <param name="fromCoord">Algebraic coordinate for square piece is moving from.</param>
		/// <param name="toCoord">Algebraic coordinate for square piece is moving toward.</param>
		/// <returns>PlayerMoveResult datatype indicating the result of the move.</returns>
		
		public PlayerMoveResult MakeMove(string fromCoord, string toCoord)
		{
			// Get square location indices and set up the result struct
			int fromSquare = SquareIndexingTools.ConvertAlgebraicToIndex(fromCoord);
			//int toSquare = SquareIndexingTools.ConvertAlgebraicToIndex(toCoord);
            int toSquare = SquareIndexingTools.ConvertAlgebraicToIndex(toCoord);
            // Modification to test AutoTest

			PlayerMoveResult pmr = new PlayerMoveResult();
			pmr.PlayerSide = PlayerToMove;
			pmr.MoveFrom = fromSquare;
			pmr.MoveTo = toSquare;
			pmr.MoveFromSAN = fromCoord;
			pmr.MoveToSAN = toCoord;

			// Check for basic illegal operations
			if(_isMate || GetPiece(fromSquare)==NONE || GetPieceColor(fromSquare)!=PlayerToMove)
			{
				pmr.PlayerPiece = NONE;
				pmr.PlayerMoveStatus = MoveResult.ILLEGAL;
				pmr.PlayerMoveType = MoveType.ILLEGAL;
				return pmr;
			}
			else
			{
				pmr.PlayerPiece = GetPiece(fromSquare);
			}

			// Check move legality
			if(!IsMoveLegit(fromSquare,toSquare))
			{
				pmr.PlayerPiece = NONE;
				pmr.PlayerMoveStatus = MoveResult.ILLEGAL;
				pmr.PlayerMoveType = MoveType.ILLEGAL;
				return pmr;
			}

			// Commit the move to the game engine
			CommitPlayerMove(ref pmr);
			if(pmr.PlayerMoveStatus==MoveResult.ILLEGAL || pmr.PlayerMoveType==MoveType.ILLEGAL)
			{
				return pmr;
			}

			// Perform check and mate analyses
			AnalyzeForCheckAndMate(ref pmr);
			if(pmr.PlayerMoveStatus==MoveResult.ILLEGAL)
			{
				pmr.PlayerMoveType = MoveType.ILLEGAL;
				return pmr;
			}
			
			// Build the SAN move string for pawn promotions and checks or mates
			if((_MoveHistory.Count > 1 && _MoveHistory.Count % 2 == 1 && 
				pmr.PlayerSide==PlayerTurn.White) || _MoveHistory.Count==1) _fullMoves++;
			pmr.MoveSAN = GetLastMoveSAN();
			if(pmr.PlayerMoveType==MoveType.PROMOTION)
			{
				pmr.MoveSAN += "=" + GetSANPieceCode(pmr.PromotedPiece);
			}
			if(pmr.PlayerMoveStatus==MoveResult.CHECK || pmr.PlayerMoveStatus==MoveResult.MATE)
			{
				if(pmr.PlayerMoveStatus==MoveResult.CHECK) pmr.MoveSAN+="+";
				if(pmr.PlayerMoveStatus==MoveResult.MATE) pmr.MoveSAN+="#";
			}
		
			// Finish the move off;  concatenate the SAN move string to the list and
			// increment the full moves counter before returning control.
			SwitchSides();
			AddSANMove(pmr.MoveSAN,pmr.PlayerSide);
			//if(pmr.PlayerSide==PlayerTurn.Black) _fullMoves++;
			return pmr;
		}

		/// <summary>
		/// Publicly-accessible method for undoing the last player move.
		/// </summary>
		/// <returns>TRUE if the undo was successful, FALSE if there was an error or no moves were available to undo.</returns>
		/// <remarks>
		/// This method is a workaround because the engine relies internally on RetractLastMove() when testing
		/// various piece movement legality.  Ideally, in future releases, this testing will be relocated into
		/// separate methods.
		/// </remarks>
		public bool UndoLastMove()
		{
			if(_MoveHistory.Count==0) return false;
			MoveHistoryItem lastMove = GetLastMoveItem();

			if(RetractLastMove())
			{
				Debug.WriteLine("BEFORE:\t_fullMoves: " + _fullMoves.ToString() + "\t_MoveHistory.Count:" +
					_MoveHistory.Count.ToString());
				// Get a reference to the last half-move made...
				if(_MoveHistory.Count > 0)
				{
					RemoveLastSANMove((lastMove.movedPiece>0 ? PlayerTurn.White : PlayerTurn.Black));

					// We want to decrement the full moves counter for even-numbered item
					// in the move history list that also corresponds to a white piece being
					// last moved.
					if(_MoveHistory.Count % 2==0 && lastMove.movedPiece > 0)
					{
						_fullMoves--;
					}	
				}
				else
				{
					// Remove any remnants from the moves list string and reset the full moves counter.
					if(this._sbSANMoveList.Length > 0) _sbSANMoveList.Remove(0,_sbSANMoveList.Length);
					_fullMoves=0;
				}
				
				// Update the player to move flag and proceed.
				PlayerToMove = lastMove.movedPiece > 0 ? PlayerTurn.White : PlayerTurn.Black;

				Debug.WriteLine("AFTER:\t_fullMoves: " + _fullMoves.ToString() + "\t_MoveHistory.Count:" +
					_MoveHistory.Count.ToString());
				return true;
			}

			return false;
		}

		/// <summary>
		/// Rolls back the last move made, resetting related bitboards and player turn flags.
		/// </summary>
		/// <returns>TRUE if last move was retracted.</returns>
		private bool RetractLastMove()
		{
			// We can't rollback moves if they don't exist.
			if(_MoveHistory.Count == 0)
			{
				return false;
			}

			// Get the last move data
			MoveHistoryItem lastMove = GetLastMoveItem();
			//PlayerToMove = lastMove.movedPiece > 0 ? PlayerTurn.White : PlayerTurn.Black;

			// Special instance moves:  castling and en passant captures
			if(lastMove.whiteCastlingMove==true || lastMove.blackCastlingMove==true)
			{
				RetractCastlingMove();
				return true;
			} 
			else if(lastMove.enPassantCapture)
			{
				RetractEnPassantCapture();
				return true;
			}

			// Reverse the move by undoing the piece move on the game engine bitboards
			// and virtual board array, replacing any captured pieces.
			UpdateMoveBitBoards(lastMove.toSquare, lastMove.fromSquare);
			_virtualBoard[lastMove.fromSquare] = lastMove.movedPiece;
			if(lastMove.capturedPiece != NONE)
			{
				_virtualBoard[lastMove.toSquare] = lastMove.capturedPiece;
				if(lastMove.capturedPiece > 0)
				{
					_whiteCaptureCount--;
				}
				else
				{
					_blackCaptureCount--;
				}

				// Replace captured piece
				UpdateCaptureBitBoards(lastMove.toSquare);
			}
			else
			{
				_virtualBoard[lastMove.toSquare] = ChessPieceDefinition.NONE;
			}

			// Final cleanup -- self explanatory
			RestoreKingCheckFlags();
			RestorePieceMovedFlags();
			_MoveHistory.RemoveAt(_MoveHistory.Count -1);
			if(_isMate) _isMate = false;
			return true;
		}

		/// <summary>
		/// Retracts last move that involved an en passant capture.
		/// </summary>
		private void RetractEnPassantCapture()
		{
			MoveHistoryItem lastMove = GetLastMoveItem();
			if(lastMove.enPassantCapture)
			{
				UpdateMoveBitBoards(lastMove.toSquare,lastMove.fromSquare);
				UpdateVirtualBoard(lastMove.toSquare,lastMove.fromSquare);
				
				// Now we need to replace the pawn captured en passant to the virtual board array
				// and decrement the appropriate capture counter.
				int pawnCaptureSquare = (GetPieceColor(lastMove.fromSquare)==PlayerTurn.Black ? lastMove.toSquare-8 : lastMove.toSquare+8);
				_virtualBoard[pawnCaptureSquare] = lastMove.capturedPiece;
				UpdateCaptureBitBoards(pawnCaptureSquare);

				switch(lastMove.capturedPiece)
				{
					case PAWN:
						_blackCaptureCount--;
						break;

					case -PAWN:
						_whiteCaptureCount--;
						break;
				}

				// Finally, remove the en passant capture item from the move hisory
				_MoveHistory.RemoveAt(_MoveHistory.Count-1);
			}
		}

		/// <summary>
		/// Retracts last move that involved castling.
		/// </summary>
		private void RetractCastlingMove()
		{
			MoveHistoryItem lastMove = GetLastMoveItem();
			int rookMoveFrom = 0;
			int rookMoveTo = 0;

			if(lastMove.whiteCastlingMove)
			{
				_chessPosition.whiteKingMoved = false;
				if(lastMove.toSquare==WHITE_KINGSIDE_CASTLE_TO)
				{
					_chessPosition.whiteRRookMoved = false;
					rookMoveFrom = WHITE_RROOK_CASTLE_TO;
					rookMoveTo = WHITE_RROOK_CASTLE_FROM;
				}
				else if(lastMove.toSquare==WHITE_QUEENSIDE_CASTLE_TO)
				{
					_chessPosition.whiteLRookMoved = false;
					rookMoveFrom = WHITE_LROOK_CASTLE_TO;
					rookMoveTo = WHITE_LROOK_CASTLE_FROM;
				}
				
			}
			else if(lastMove.blackCastlingMove)
			{
				_chessPosition.blackKingMoved = false;
				if(lastMove.toSquare==BLACK_KINGSIDE_CASTLE_TO)
				{
					_chessPosition.blackRRookMoved = false;
					rookMoveFrom = BLACK_RROOK_CASTLE_TO;
					rookMoveTo = BLACK_RROOK_CASTLE_FROM;
				}
				else if(lastMove.toSquare==BLACK_QUEENSIDE_CASTLE_TO)
				{
					_chessPosition.blackLRookMoved = false;
					rookMoveFrom = BLACK_LROOK_CASTLE_TO;
					rookMoveTo = BLACK_LROOK_CASTLE_FROM;
				}
			}
			else
			{
				return;
			}

			// Update bitboards and virtual boards
			UpdateMoveBitBoards(lastMove.toSquare, lastMove.fromSquare);
			UpdateVirtualBoard(lastMove.toSquare, lastMove.fromSquare);
			UpdateMoveBitBoards(rookMoveFrom,rookMoveTo);
			UpdateVirtualBoard(rookMoveFrom,rookMoveTo);
			
			// ... and delete the last entry in the move history...
			_MoveHistory.RemoveAt(_MoveHistory.Count - 1);
		}

		/// <summary>
		/// Commits a validated move from MakeMove().
		/// </summary>
		/// <param name="playerMoveResult">PlayerMoveResult object containing details for the move.</param>
		private void CommitPlayerMove(ref PlayerMoveResult playerMoveResult)
		{
			playerMoveResult.PlayerMoveStatus = MoveResult.LEGAL;

			// Check for pawn promotion
			if(IsPawnPromotion(playerMoveResult.MoveFrom,playerMoveResult.MoveTo))
			{
				DoPlayerMove(playerMoveResult.MoveFrom,playerMoveResult.MoveTo);
				if(!DoPawnPromotion(playerMoveResult.MoveTo))
				{
					RetractLastMove();
					playerMoveResult.PlayerMoveStatus = MoveResult.ILLEGAL;
					playerMoveResult.PlayerMoveType = MoveType.ILLEGAL;
				}
				else
				{
					playerMoveResult.PlayerMoveType = MoveType.PROMOTION;
					playerMoveResult.PromotedPiece = GetLastMoveItem().promotedPiece;
				}	
			}
				// Check for castling
			else if(IsCastlingMove(playerMoveResult.MoveFrom, playerMoveResult.MoveTo))
			{
				CommitCastlingMove(playerMoveResult.MoveFrom,playerMoveResult.MoveTo);
				if(_chessPosition.whiteLRookMoved==true || _chessPosition.blackLRookMoved==true)
				{
					playerMoveResult.PlayerMoveType = MoveType.QUEENSIDE_CASTLE;
				}
				else if(_chessPosition.whiteRRookMoved==true || _chessPosition.blackRRookMoved==true)
				{
					playerMoveResult.PlayerMoveType = MoveType.KINGSIDE_CASTLE;
				}
			}
				// Check for en passant
			else if(_chessPosition.enPassantAvailable) // En-passant capture move confirmed
			{
				CommitEnPassantCapture(playerMoveResult.MoveFrom, playerMoveResult.MoveTo);
				playerMoveResult.PlayerMoveType = MoveType.ENPASSANT;
			}
			else // Normal capture or non-capture move
			{
				if(GetPiece(playerMoveResult.MoveTo)==NONE)
				{
					playerMoveResult.PlayerMoveType = MoveType.NONCAPTURE;
				}
				else
				{
					playerMoveResult.PlayerMoveType = MoveType.CAPTURE;
				}
				DoPlayerMove(playerMoveResult.MoveFrom, playerMoveResult.MoveTo);
			}
		}

		/// <summary>
		/// Commits a validated move and updates respective bitboards and arrays
		/// and piece capture counts
		/// </summary>
		/// <param name="fromSquare"></param>
		/// <param name="toSquare"></param>
		private void DoPlayerMove(int fromSquare, int toSquare)
		{
			//TODO: Refactor Target - CC Score 24
            MoveHistoryItem mhi = new MoveHistoryItem();
			mhi.capturedPiece = NONE;
			
			// Update the move history collection...
			if(PlayerToMove == PlayerTurn.White)
			{
				// Do standard capture
				if(GetPiece(toSquare) != NONE)
				{
					_whiteCaptureCount++;
					mhi.capturedPiece = GetPiece(toSquare);
				}
				
				// Do en passant capture
				if(GetPiece(fromSquare)==PAWN && GetPiece(toSquare)==NONE && _chessPosition.enPassantAvailable)
				{
					_whiteCaptureCount++;
					mhi.capturedPiece = GetPiece(toSquare+8);
				}

				// Is this the first move of either white rook?
				if(GetPiece(fromSquare) == ROOK)
				{
					if(fromSquare == 56 && _chessPosition.whiteLRookMoved == false)
					{
						_chessPosition.whiteLRookMoved = true;
						mhi.whiteLeftRookMoved = true;
					}
					else if(fromSquare == 63 && _chessPosition.whiteRRookMoved == false)
					{
						_chessPosition.whiteRRookMoved = true;
						mhi.whiteRightRookMoved = true;
					}
				}

				// Is this the first move of the white king?
				if(fromSquare == 60 && _chessPosition.whiteKingMoved == false)
				{
					_chessPosition.whiteKingMoved = true;
					mhi.whiteKingMoved = true;
				}
			}
			else
			{
				// Standard capture
				if(GetPiece(toSquare) != NONE)
				{
					_blackCaptureCount++;
					mhi.capturedPiece = GetPiece(toSquare);
				}

				// En Passant capture
				if(GetPiece(fromSquare)==-PAWN && GetPiece(toSquare)==NONE && _chessPosition.enPassantAvailable)
				{
					_blackCaptureCount++;
					mhi.capturedPiece = GetPiece(toSquare-8);
				}
				
				// Check black rook moves
				if(GetPiece(fromSquare) == -ROOK)
				{
					// Is this the first move of either black rook?
					if(fromSquare == 0 && _chessPosition.blackLRookMoved == false)
					{
						_chessPosition.blackLRookMoved = true;
						mhi.blackLeftRookMoved = true;
					}
					else if(fromSquare == 7 && _chessPosition.blackRRookMoved == false)
					{
						_chessPosition.blackRRookMoved = true;
						mhi.blackLeftRookMoved = true;
					}
				}
				
				// Is this the first move of the black king?
				if(fromSquare==4 && _chessPosition.blackKingMoved == false)
				{
					_chessPosition.blackKingMoved = true;
					mhi.blackKingMoved = true;
				}
			}
			
			// Store relevant move history data
			mhi.fromSquare = fromSquare;
			mhi.toSquare = toSquare;
			mhi.movedPiece = GetPiece(fromSquare);
			mhi.preMoveBitBoard = _chessPosition.whitePieces | _chessPosition.blackPieces;
			mhi.prePieceTypeBitBoard = GetPieceTypeBitBoard(mhi.movedPiece);

			// Update related bitboards for the chessboard and pieces
			UpdateMoveBitBoards(fromSquare,toSquare);
			mhi.postMoveBitBoard = _chessPosition.whitePieces | _chessPosition.blackPieces;
			
			// Update the virtual board
			UpdateVirtualBoard(fromSquare,toSquare);
			
			// Store in move history list
			_MoveHistory.Add(mhi);
			
		}
		
		/// <summary>
		/// Commits a given castling move to the game bitboards, virtual board array and move
		/// history list.
		/// </summary>
		/// <remarks>
		/// This method assumes that the castling move has been tested for legality.
		/// </remarks>
		/// <param name="fromSquare">Index of square (0-63) that king is moving from.</param>
		/// <param name="toSquare">Index of square (0-63) that king is moving to.</param>
		private void CommitCastlingMove(int fromSquare, int toSquare)
		{
			MoveHistoryItem mhi = new MoveHistoryItem();
			mhi.movedPiece = GetPiece(fromSquare);
			mhi.fromSquare = fromSquare;
			mhi.toSquare = toSquare;
			mhi.preMoveBitBoard = _chessPosition.whitePieces | _chessPosition.blackPieces;
			int rookFromSquare = 0;
			int rookToSquare = 0;
			
			// Determine the side and type of castling so that we can tell where
			// to move the required rook (queenside or kingside)
			if(PlayerToMove==PlayerTurn.White)
			{
				mhi.whiteKingMoved = true;
				mhi.whiteCastlingMove = true;
				_chessPosition.whiteKingMoved = true;
				if(toSquare==WHITE_KINGSIDE_CASTLE_TO)
				{
					mhi.whiteRightRookMoved = true;
					_chessPosition.whiteRRookMoved = true;
					rookFromSquare = WHITE_RROOK_CASTLE_FROM;
					rookToSquare = WHITE_RROOK_CASTLE_TO;
				}
				else if(toSquare==WHITE_QUEENSIDE_CASTLE_TO)
				{
					mhi.whiteLeftRookMoved = true;
					_chessPosition.whiteLRookMoved = true;
					rookFromSquare = WHITE_LROOK_CASTLE_FROM;
					rookToSquare = WHITE_LROOK_CASTLE_TO;
				}
			}
			else
			{
				mhi.blackKingMoved = true;
				mhi.blackCastlingMove = true;
				_chessPosition.blackKingMoved = true;
				if(toSquare==BLACK_KINGSIDE_CASTLE_TO)
				{
					mhi.blackRightRookMoved = true;
					_chessPosition.blackRRookMoved = true;
					rookFromSquare = BLACK_RROOK_CASTLE_FROM;
					rookToSquare = BLACK_RROOK_CASTLE_TO;
				}
				else if(toSquare==BLACK_QUEENSIDE_CASTLE_TO)
				{
					mhi.blackLeftRookMoved = true;
					_chessPosition.blackLRookMoved = true;
					rookFromSquare = BLACK_LROOK_CASTLE_FROM;
					rookToSquare = BLACK_LROOK_CASTLE_TO;
				}
			}

			// Move the King
			UpdateMoveBitBoards(fromSquare,toSquare);			 
			UpdateVirtualBoard(fromSquare,toSquare);
			// Move the Rook
			UpdateMoveBitBoards(rookFromSquare,rookToSquare);
			UpdateVirtualBoard(rookFromSquare,rookToSquare);

			// Record the post-move bitboard and add to the list.
			mhi.postMoveBitBoard = _chessPosition.whitePieces | _chessPosition.blackPieces;
			_MoveHistory.Add(mhi);

		}

		/// <summary>
		/// Commits a verified en passant capture to the game bitboards and virtual board array and
		/// records the move in the move history list.
		/// </summary>
		/// <param name="fromSquare">Index (0-63) for the pawn making the en-passant capture.</param>
		/// <param name="toSquare">Index (0-63) for the pawn, post-capture.</param>
		private void CommitEnPassantCapture(int fromSquare, int toSquare)
		{
			if(!_chessPosition.enPassantAvailable) return;

			PlayerTurn pieceColor = GetPieceColor(fromSquare);
			int captureSquare = (pieceColor==PlayerTurn.Black) ? toSquare-8 : toSquare+8;

			// Set up for tracking the move
			MoveHistoryItem mhi = new MoveHistoryItem();
			mhi.movedPiece = GetPiece(fromSquare);
			mhi.fromSquare = fromSquare;
			mhi.toSquare = toSquare;
			mhi.preMoveBitBoard = _chessPosition.whitePieces | _chessPosition.blackPieces;
			mhi.capturedPiece = GetPiece(captureSquare);

			// Move the en-passant capturing pawn
			UpdateMoveBitBoards(fromSquare,toSquare);
			UpdateVirtualBoard(fromSquare,toSquare);

			// Remove the victim
			UpdateCaptureBitBoards(captureSquare);
			_virtualBoard[captureSquare] = NONE;

			// Add to the move history list
			mhi.enPassantCapture = true;
			_MoveHistory.Add(mhi);
			_chessPosition.enPassantAvailable = false;
		}

		/// <summary>
		/// Performs the pawn promotion event loop to request the piece type to 
		/// promote a player's pawn into, setting it on completion.
		/// </summary>
		/// <param name="pawnSquare">Index (0-63) of pawn to promote.</param>
		/// <returns>TRUE if promotion successful.</returns>
		private bool DoPawnPromotion(int pawnSquare)
		{
			Piece promotePawnTo = NONE;
			Piece sourcePawn = GetPiece(pawnSquare);
			PawnPromotionEventArgs ppe = new PawnPromotionEventArgs(promotePawnTo);
			ppe.PromotionSide = PlayerToMove;

			if(sourcePawn!=PAWN && sourcePawn!=-PAWN) return false;
			if(PlayerToMove==PlayerTurn.Black && _chessPosition.blackKingCheck==true) return false;
			if(PlayerToMove==PlayerTurn.White && _chessPosition.whiteKingCheck==true) return false;

			// Continually raise event until user supplies valid piece.
			while(ppe.PromotedPiece==NONE)
			{
				OnPawnPromotion(ref ppe);
				if(ppe.PromotedPiece > 0 && ppe.PromotionSide != PlayerTurn.White ||
					ppe.PromotedPiece < 0 && ppe.PromotionSide != PlayerTurn.Black)
				{
					// User supplied wrong piece color-- go again
					ppe.PromotedPiece=NONE;
				}
				if(Math.Abs(ppe.PromotedPiece)==KING || Math.Abs(ppe.PromotedPiece)==PAWN)
				{
					// Can't upgrade to a PAWN or KING -- go again
					ppe.PromotedPiece=NONE;
				}
			}

			// Upgrade the pawn and move history record
			_virtualBoard[pawnSquare] = ppe.PromotedPiece;
			UpdateBitBoardsForPromotion(pawnSquare,ppe.PromotedPiece);
			MoveHistoryItem mhi = GetLastMoveItem();
			mhi.movedPiece = sourcePawn;
			mhi.promotedPiece = ppe.PromotedPiece;
			_MoveHistory[_MoveHistory.Count-1] = mhi;
			
			return true;
		}
		// -- GROUP END --

		// GROUP: PGN Notation Building Methods

		/// <summary>
		/// Gets the Standard Algebraic Notation piece code for a virtual board piece value.
		/// </summary>
		/// <param name="pieceValue">Virtual board Piece.</param>
		/// <returns>char representing the piece type, ie P,N,B,R,Q,K
		/// A single space is returned if pieceValue evaluates to NONE.
		/// </returns>
		private char GetSANPieceCode(Piece pieceValue)
		{
			string code = _SANPieceCodes[Math.Abs(pieceValue)].ToString().ToUpper();
			return code[0];
		}

		/// <summary>
		/// Constructs a SAN string from the last move in the rules engine move history collection.
		/// </summary>
		/// <returns>The SAN for a given move as string without modifiers indicating check, checkmate or pawn promotion.</returns>
		private string GetLastMoveSAN()
		{
			MoveHistoryItem mhi = GetLastMoveItem();
			string moveSAN = "";
            string squareCoord = SquareIndexingTools.AlgebraicBoardIndex[mhi.fromSquare];
			
			// Return notation for castling
			if((mhi.blackCastlingMove || mhi.whiteCastlingMove))
			{
				if((mhi.blackRightRookMoved || mhi.whiteRightRookMoved)) return "O-O";
				if((mhi.blackLeftRookMoved || mhi.whiteLeftRookMoved)) return "O-O-O";
			}
	
			// Get the character for the piece type-- pawns are excluded from this in SAN.
			if(Math.Abs(mhi.movedPiece) != PAWN)
			{
				moveSAN = GetSANPieceCode(mhi.movedPiece).ToString();
			}

			// Check if multiple pieces of same type are attacking the same square
			BitBoard ambiguousPieces = 0;
			if(!IsMoveDisambiguous(mhi,out ambiguousPieces))
			{
				// Implement 3-stage SAN specification to remove piece ambiguity for notation
				// Get rank and file state bitboards representing all squares along each, exclusive
				// of the originating piece square.
				
				// a) Can pieces be distinguished by FILE?
				// --> Paradoxically, we'll use the _RankAttacks bitboards here to draw a virtual
				//	   "ruler" vertically across the board to determine if pieces are on the same file.
				BitBoard validSquares = GetRotatedBitBoard(_RookMoves[mhi.fromSquare],RotateBitBoardBy.Right90Degrees);
				int fileState = (int)(validSquares >> RotatedBitBoard.ShiftBitsIndex[mhi.fromSquare]) & 255;
				BitBoard fileDistTest = _RankAttacks[RotatedBitBoard.Right90[mhi.fromSquare],fileState] << 
					RotatedBitBoard.ShiftBitsIndex[RotatedBitBoard.Right90[mhi.fromSquare]];
				fileDistTest = GetRotatedBitBoard(fileDistTest,RotateBitBoardBy.Left90Degrees);
				if((fileDistTest & ambiguousPieces) == 0)
				{
					// Pieces can be distinguished by their respective FILE
					// Add the originating square FILE letter to the piece code
					moveSAN+=squareCoord.ToLower()[0];
				}
				else
				{
					// b) Can pieces be distinguished by RANK?
					// --> As with the FILE detection, we'll go opposite here as well and use the _FileAttacks bitboards
					//     to draw a virtual horizontal "ruler" across the board to determine if pieces are on the same rank.
					BitBoard rankSquares = _FileAttacks[mhi.fromSquare,0];
					BitBoard rankDistTest = rankSquares << RotatedBitBoard.ShiftBitsIndex[mhi.fromSquare];
					if((rankDistTest & ambiguousPieces) != 0)
					{
						// Pieces can be distinguished by RANK
						// Add the originating square RANK number to the piece code
						moveSAN+=squareCoord[1];
					}
					else
					{
						// c) Fail-over to using complete square notation.
						moveSAN+=squareCoord.ToLower();
					}
				}

			}
			
			// Build destination portion and return result
			if(mhi.capturedPiece != NONE)
			{
				// Pawn captures inlcude the file letter of the originating square
				if(mhi.movedPiece==PAWN || mhi.movedPiece==-PAWN)
				{
					moveSAN += (moveSAN=="") ? squareCoord.ToLower()[0] + "x" : "x";
				}
				else
				{
					moveSAN+="x";
				}
			}

			return moveSAN += SquareIndexingTools.AlgebraicBoardIndex[mhi.toSquare].ToLower();

		}

		/// <summary>
		/// Determines if the chess pieces of the same color and type are attacking the same target square.  If more
		/// than two are attacking the same square, SAN specs require disambiguity tests to construct the notation.
		/// </summary>
		/// <param name="lastMoveItem">MoveHistoryItem object that contains the details for the move
		/// to check against ambiguity. 
		/// </param>
		/// <param name="ambiguousPieces">Output parameter; a BitBoard that will either contain the
		/// pieces involved in an ambiguous attack (ie both attacking the same square) or otherwise evaluate to zero.
		/// </param>
		/// <returns>TRUE if move is disambiguous, ie only one piece of the provided type is attacking the target square.</returns>
		private bool IsMoveDisambiguous(MoveHistoryItem lastMoveItem, out BitBoard ambiguousPieces)
		{
			bool result=true;
			BitBoard piecePositions = lastMoveItem.prePieceTypeBitBoard;
			int targetSquare = lastMoveItem.toSquare;
			int fromSquare = lastMoveItem.fromSquare;
			Piece pieceType = lastMoveItem.movedPiece;
			ambiguousPieces=0;

			// Return true for kings -- can only have one per side...
			if(pieceType==KING || pieceType==-KING) return true;

			// Check for pawn moves here-- only pawn attacks can incur ambiguities
			if((pieceType==PAWN && (piecePositions & _wPawnMoves[fromSquare])==0) ||
				(pieceType==-PAWN && (piecePositions & _bPawnMoves[fromSquare])==0))
			{
				return true;
			}

			// Evaluate attacking piece types individually...
			switch(pieceType)
			{
				case PAWN:
					ambiguousPieces = piecePositions & _bPawnAttacks[targetSquare];
					break;
				case -PAWN:
					ambiguousPieces = piecePositions & _wPawnAttacks[targetSquare];
					break;
				case KNIGHT: case -KNIGHT:
					ambiguousPieces = piecePositions & _KnightAttacks[targetSquare];
					break;
				case BISHOP: case -BISHOP:
					ambiguousPieces = piecePositions & _BishopAttacks[targetSquare];
					break;
				case ROOK: case -ROOK:
					ambiguousPieces = piecePositions & _RookMoves[targetSquare];
					break;
				case QUEEN: case -QUEEN:
					ambiguousPieces = piecePositions & _QueenMoves[targetSquare];
					break;
				default:
					result = false;
					break;
			}
			
			// Get the bitcount of the combined BitBoards-- a value of 2 or more indicates
			// multiple pieces attacking the same square-- ambiguity exists.
			result = (GetBitCount(ambiguousPieces) > 1) ? false : true;
			if(result) ambiguousPieces = 0;
			return result;
		}

		/// <summary>
		/// Returns the number of "bits" turned on in a given BitBoard.
		/// </summary>
		/// <param name="chessPieceBitBoard">Chess position BitBoard to analyze.</param>
		/// <returns>Int count of the bits turned on in the bitboard.</returns>
		private int GetBitCount(BitBoard chessPieceBitBoard)
		{
			int bitCount=0;
			for(int sq=0; sq<64; sq++)
			{
				if((chessPieceBitBoard & _bitMask[sq]) != 0) bitCount++;
			}
			return bitCount;
		}

		/// <summary>
		/// Adds move to the internal SAN moves stringbuilder.
		/// </summary>
		private void AddSANMove(string SANMoveString, PlayerTurn sideToRecord)
		{
			if(sideToRecord==PlayerTurn.White)
			{
				string moveNum = (_fullMoves).ToString() + ". ";
				_sbSANMoveList.Append(moveNum + SANMoveString + " ");				
			}
			else
			{
				_sbSANMoveList.Append(SANMoveString + " ");
			}
		}

		/// <summary>
		/// Removes last move from the intern SAN moves stringbuilder.  
        /// If there are no entries left, the method does nothing.
		/// </summary>
		private void RemoveLastSANMove(PlayerTurn sideToRemove)
		{
			if(_sbSANMoveList.Length==0) return;
			if(_fullMoves==0)
			{
				// We're at the beginning of the list
				_sbSANMoveList.Remove(0,_sbSANMoveList.Length);
				return;
			}
			if(sideToRemove==PlayerTurn.White)
			{
				// We're in the middle of the list
				Regex rx = new Regex(@"\d+\.{1}\s",RegexOptions.RightToLeft);
				int pos1 = rx.Match(_sbSANMoveList.ToString()).Index;
				if(pos1==-1) return;
				_sbSANMoveList.Remove(pos1,_sbSANMoveList.Length - pos1);
			}
			else
			{
				int pos1 = _sbSANMoveList.ToString().TrimEnd().LastIndexOf(" ");
				_sbSANMoveList.Remove(pos1,_sbSANMoveList.Length - (pos1 + 1));
			}
		}
		// -- GROUP END --

		// GROUP: Rules Engine Event Raising Methods
		/// <summary>
		/// Raises RNChessRulesEngine.PawnPromotion event, indicating that a player has successfully moved their
		/// pawn into the last rank for their side.
		/// </summary>
		/// <param name="e">Pawn promotion object.  Stores the piece type that the player wants to promote their
		/// pawn into.</param>
		protected void OnPawnPromotion(ref PawnPromotionEventArgs e)
		{
			if(_pawnPromotionEvent != null)
			{
				_pawnPromotionEvent(this,e);
			}
		}
		// -- GROUP END --

		// GROUP: BitBoard Initialization Routines
		/// <summary>
		/// Initialize internal bitmask array for each square on the board (64)
        /// and fifth rank bitmasks for white and black sides.
		/// </summary>
		private void InitBitmasks()
		{
			BitBoard bit = 1;
			for(int square=0; square < TOTAL_SQUARES; square++)
			{
				// set each bitmask by shifting a bit one
				// position to the right for each square (after 0)
				_bitMask[square] = (bit << square);
			}

            // Initialize the bitmasks for fifth ranks of white and black pawns
            _whiteFifthRankBitMask = 255;
            _whiteFifthRankBitMask <<= 24;
            _blackFifthRankBitMask = 255;
            _blackFifthRankBitMask <<= 32;
		}


		/// <summary>
		/// Initialize internal bitboards for tracking piece movement
		/// </summary>
		private void InitBitBoards()
		{
			// Zero the chess position bitboards before loading them with any new configuration
			// and set the king and rook movement flags to zero.
			ResetBitBoards();
			ResetGameFlags();

			for(int square=0; square < TOTAL_SQUARES; square++)
			{
				switch(_virtualBoard[square])
				{
					case -ROOK:
						_chessPosition.blackPieces |= _bitMask[square];
						_chessPosition.blackRooks |= _bitMask[square];
						_chessPosition.rooksQueens |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case -KNIGHT:
						_chessPosition.blackPieces |= _bitMask[square];
						_chessPosition.blackKnights |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case -BISHOP:
						_chessPosition.blackPieces |= _bitMask[square];
						_chessPosition.blackBishops |= _bitMask[square];
						_chessPosition.bishopsQueens |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case -QUEEN:
						_chessPosition.blackPieces |= _bitMask[square];
						_chessPosition.blackQueens |= _bitMask[square];
						_chessPosition.rooksQueens |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case -KING:
						_chessPosition.blackPieces |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case -PAWN:
						_chessPosition.blackPieces |= _bitMask[square];
						_chessPosition.blackPawns |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case ROOK:
						_chessPosition.whitePieces |= _bitMask[square];
						_chessPosition.whiteRooks |= _bitMask[square];
						_chessPosition.rooksQueens |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case KNIGHT:
						_chessPosition.whitePieces |= _bitMask[square];
						_chessPosition.whiteKnights |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case BISHOP:
						_chessPosition.whitePieces |= _bitMask[square];
						_chessPosition.whiteBishops |= _bitMask[square];
						_chessPosition.bishopsQueens |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case QUEEN:
						_chessPosition.whitePieces |= _bitMask[square];
						_chessPosition.whiteQueens |= _bitMask[square];
						_chessPosition.rooksQueens |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case KING:
						_chessPosition.whitePieces |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;

					case PAWN:
						_chessPosition.whitePieces |= _bitMask[square];
						_chessPosition.whitePawns |= _bitMask[square];
						SetRotatedBitBoards(square);
						break;
				}
			}
		}

		/// <summary>
		/// Resets all the chesspiece bitboards to zero, i.e. BLANK.
		/// </summary>
		private void ResetBitBoards()
		{
			// Potential issues-- I've left out resetting the black and white
			// king squares here, because their positions are fixed when the
			// LoadVirtualBoard() methods are called.
			_chessPosition.blackPieces = 0;
			_chessPosition.blackPawns = 0;
			_chessPosition.blackKnights = 0;
			_chessPosition.blackBishops = 0;
			_chessPosition.blackRooks = 0;
			_chessPosition.blackQueens = 0;
			
			_chessPosition.whitePieces = 0;
			_chessPosition.whitePawns = 0;
			_chessPosition.whiteKnights = 0;
			_chessPosition.whiteBishops = 0;
			_chessPosition.whiteRooks = 0;
			_chessPosition.whiteQueens = 0;

			// Reset the rotated bitboards.
			for(int sq=0; sq < 64; sq++)
			{
				ClearRotatedBitBoards(sq);
			}
		}

		/// <summary>
		/// Resets the flags for king and rook movements to FALSE.
		/// </summary>
		private void ResetGameFlags()
		{
			_chessPosition.blackKingCheck = false;
			_chessPosition.blackKingMoved = false;
			_chessPosition.blackLRookMoved = false;
			_chessPosition.blackRRookMoved = false;

			_chessPosition.whiteKingCheck = false;
			_chessPosition.whiteKingMoved = false;
			_chessPosition.whiteLRookMoved = false;
			_chessPosition.whiteRRookMoved = false;

			_chessPosition.enPassantAvailable = false;
		}

		/// <summary>
		/// Turns on the bit for the given square in ALL rotated bitboards
		/// </summary>
		/// <param name="currentSquareIndex"></param>
		private void SetRotatedBitBoards(int currentSquareIndex)
		{
			_chessPosition.RotateRight90 |= _bitMask[RotatedBitBoard.Right90[currentSquareIndex]];
			_chessPosition.RotateLeft90 |= _bitMask[RotatedBitBoard.Left90[currentSquareIndex]];
			_chessPosition.RotateRight45 |= _bitMask[RotatedBitBoard.DiagA8H1Map[currentSquareIndex]];
			_chessPosition.RotateLeft45 |= _bitMask[RotatedBitBoard.DiagA1H8Map[currentSquareIndex]];
		}

		/// <summary>
		/// Turns off the bit for a given square in ALL rotated bitboards
		/// </summary>
		/// <param name="currentSquareIndex"></param>
		private void ClearRotatedBitBoards(int currentSquareIndex)
		{
			_chessPosition.RotateRight90 |= 
				(_bitMask[RotatedBitBoard.Right90[currentSquareIndex]] & 0);
			_chessPosition.RotateLeft90 |= 
				(_bitMask[RotatedBitBoard.Left90[currentSquareIndex]] & 0);
			_chessPosition.RotateRight45 |= 
				(_bitMask[RotatedBitBoard.DiagA8H1Map[currentSquareIndex]] & 0);
			_chessPosition.RotateLeft45 |= 
				(_bitMask[RotatedBitBoard.DiagA1H8Map[currentSquareIndex]] & 0);
		}

		/// <summary>
		/// Constructs bitboard masks for valid attack squares for each
		/// chesspiece.
		/// </summary>
		private void InitAttackBoards()
		{			
			// Build attack boards
			for(int square=0;square<TOTAL_SQUARES;square++)
			{
				if(square > 7)			// black pawns
				{
					PawnAttackSquares(square);
					PawnMoveSquares(square);
				}
				if(square < 56)			// white pawns
				{
					PawnAttackSquares(square);
					PawnMoveSquares(square);
				}

				InitKnightAttackSquares(square);
				InitBishopQueenMoveSquares(square);
				InitRookQueenMoveSquares(square);
				InitKingAttackSquares(square);
				InitDiagonalAttacks(square);
				InitRankAndFileAttacks(square);
			}
		}
		

		/// <summary>
		/// Initialize diagonal attack lookup arrays
		/// </summary>
		/// <param name="square"></param>
		private void InitDiagonalAttacks(int square)
		{
			int result = 0;
			// Initialize diagonal attack arrays
			// number of diagonal "states" will vary with length of diagonal
			int diagA8H1Length = RotatedBitBoard.DiagonalLengthA8H1[square];
			int diagA1H8Length = RotatedBitBoard.DiagonalLengthA1H8[square];
			int diagA8H1States = (int)Math.Pow(2,(double)diagA8H1Length)-1;
			int diagA1H8States = (int)Math.Pow(2,(double)diagA1H8Length)-1;

			// Instantiate jagged array
			_DiagonalA8H1Attacks[square] = new BitBoard[diagA8H1States];
			_DiagonalA1H8Attacks[square] = new BitBoard[diagA1H8States];
			
			// Potential Problem:
			// Is the value of square appropriate for finding the correct
			// attack squares?  For ex: square 61 (F1) is translated into
			// square 5 for calculations, yet it should be treated as 0
			// for A8H1 or 4 for A1H8-- should the value of square be
			// rotated first?  Hmmm.

			int leftSquare = RotatedBitBoard.Left45[square];
			int rightSquare = RotatedBitBoard.Right45[square];
			int tSquare = RotatedBitBoard.DiagonalSquares[leftSquare];

			// Loop through the "states" of the A8H1 diagonal
			for(int diagA8H1 = 0; diagA8H1 < diagA8H1States;  diagA8H1++)
			{
				result = FindAttackSquares(tSquare,diagA8H1,RotatedBitBoard.DiagonalLengthA8H1[square]);
				//BitBoard result2 = (result << (8 - (RotatedBitBoard.DiagonalLengthA8H1[rightSquare])));
				_DiagonalA8H1Attacks[square][diagA8H1] = (BitBoard)result;
			}
			
			tSquare = RotatedBitBoard.DiagonalSquares[rightSquare];

			// Loop through the "states" of the A1H8
			for(int diagA1H8 = 0; diagA1H8 < diagA1H8States; diagA1H8++)
			{
				result = FindAttackSquares(tSquare,diagA1H8,RotatedBitBoard.DiagonalLengthA1H8[square]);
				_DiagonalA1H8Attacks[square][diagA1H8] = (BitBoard)result;
			}
		}


		/// <summary>
		/// Initialize rank and file attack lookup arrays
		/// </summary>
		/// <param name="square">Index of square (0-63) to create the rank and file attack arrays from.</param>
		private void InitRankAndFileAttacks(int square)
		{
			int result = 0;
			// Construct rank and file attack boards
			for(int rankState=0; rankState<256; rankState++)
			{
				result = FindAttackSquares(square,rankState,8);
				_RankAttacks[square,rankState] = (BitBoard)result;
				// Note that the arrays for rank and file attacks are
				// essentially the same-- we'll just reference a 90 degree
				// right rotated bitboard index array to map the results
				// appropriately
				_FileAttacks[square,rankState] = (BitBoard)result;
			}
		}

		/// <summary>
		/// Returns 8 bit int representing available squares for occupation
		/// on a file given obstructions and the current square index
		/// </summary>
		/// <param name="currentSquareIndex">Square index (0-63)</param>
		/// <param name="rankState">Evaluates to 8-bit number (0-255) representing the "state" of the rank/file/diagonal</param>
		/// <param name="length">Number of bits to evaluate.</param>
		private int FindAttackSquares(int currentSquareIndex, int rankState, int length)
		{
			int start = 0;
			int result = 0;

			// Convert square index into range 0-7
			int rankSquare = currentSquareIndex & 7;
			
			// Remember:  left and right are inverted
			// Find attacks to the left of current square
			if(rankSquare < length)
			{
				start = 1 << (rankSquare + 1);
				while(start < 256)
				{
					result |= start;
					if((rankState & start) != 0)
						break;
					start <<= 1;	// left shift bits ~ value increases
				}
			}

			// Find attacks to the right of current square
			if(rankSquare > 0)
			{
				start = 1 << (rankSquare - 1);
				while(start > 0)
				{
					result |= start;
					if((rankState & start) != 0)
						break;
					start >>= 1;	// right shift bits ~ value decreases
				}
			}

			// AND result with mask calculated from length of rank/file/diagonal
			// Trims the result to the number of bits we're concerned with
			result &= ((1 << length )-1);
			return result;
		}


		/// <summary>
		/// Initializes black and white pawn attack bitboards
		/// </summary>
		/// <param name="currentSquareIndex">Index (0-63) of the square to initialize.</param>
		/// <returns></returns>
		private void PawnAttackSquares(int currentSquareIndex)
		{
			int targetSquareIndex;
			foreach(int test in PAWN_ATTACK_SQUARE)
			{				
				if(currentSquareIndex > 7)
				{
					targetSquareIndex = currentSquareIndex + test;
					if(ValidPawnCapture(currentSquareIndex,targetSquareIndex))
					{
						_bPawnAttacks[currentSquareIndex] |= _bitMask[targetSquareIndex];
					}
				}
				if(currentSquareIndex < 56)
				{
					targetSquareIndex = currentSquareIndex - test;
					if(ValidPawnCapture(currentSquareIndex,targetSquareIndex))
					{
						_wPawnAttacks[currentSquareIndex] |= _bitMask[targetSquareIndex];
					}
				}
			}
		}


		/// <summary>
		/// Initializes black and white pawn move bitboards
		/// </summary>
		/// <param name="currentSquareIndex"></param>
		private void PawnMoveSquares(int currentSquareIndex)
		{
			int targetSquareIndex;
			foreach(int test in PAWN_MOVE_SQUARE)
			{
				// Valid first move squares
				if(currentSquareIndex > 7 && currentSquareIndex < 16)
				{
					targetSquareIndex = currentSquareIndex + test;
					if(ValidPawnFirstMove(currentSquareIndex,targetSquareIndex))
					{
						_bPawnMoves[currentSquareIndex] |= _bitMask[targetSquareIndex];
					}
				}
				if(currentSquareIndex < 56 &&  currentSquareIndex > 47)
				{
					targetSquareIndex = currentSquareIndex - test;
					if(ValidPawnFirstMove(currentSquareIndex,targetSquareIndex))
					{
						_wPawnMoves[currentSquareIndex] |= _bitMask[targetSquareIndex];
					}
				}

				// Valid subsequent move squares
				if(currentSquareIndex > 15)
				{
					targetSquareIndex = currentSquareIndex + test;
					if(ValidPawnMove(currentSquareIndex,targetSquareIndex))
					{
						_bPawnMoves[currentSquareIndex] |= _bitMask[targetSquareIndex];
					}
				}
				if(currentSquareIndex < 48)
				{
					targetSquareIndex = currentSquareIndex - test;
					if(ValidPawnMove(currentSquareIndex,targetSquareIndex))
					{
						_wPawnMoves[currentSquareIndex] |= _bitMask[targetSquareIndex];
					}
				}
			}
		}

		/// <summary>
		/// Initializes black and white knight attack bitboards
		/// </summary>
		/// <param name="currentSquareIndex"></param>
		private void InitKnightAttackSquares(int currentSquareIndex)
		{
			int targetSquareIndex;
			foreach(int test in KNIGHT_ATTACK_SQUARE)
			{
				targetSquareIndex = currentSquareIndex + test;
				if((targetSquareIndex > -1) && (targetSquareIndex < 64))
				{
					if(ValidKnightCapture(currentSquareIndex,targetSquareIndex))
					{
						_KnightAttacks[currentSquareIndex] |= _bitMask[targetSquareIndex];	
					}
				}
			}
		}


		/// <summary>
		/// Initializes black and white bishop and queen attack bitboards
		/// square masking bits
		/// </summary>
		/// <param name="currentSquareIndex"></param>
		private void InitBishopQueenMoveSquares(int currentSquareIndex)
		{
			int targetSquareIndex = 0;
			int lastSquareIndex = 0;
			foreach(int test in BISHOP_ATTACK_SQUARE)
			{
				lastSquareIndex = currentSquareIndex;
				targetSquareIndex = currentSquareIndex + test;
				
				while(ValidBishopQueenMove(lastSquareIndex,targetSquareIndex))
				{
					_BishopMoves[currentSquareIndex] |= _bitMask[targetSquareIndex];
					_QueenMoves[currentSquareIndex] |= _bitMask[targetSquareIndex];

					// Initialize the +7,+9,-7,-9 diagonal directional bitboards while we've
					// got the computed attack squares available-- these will be used
					// for obstruction detection later
					switch(test)
					{
						case 7:
							_squarePlus_7[currentSquareIndex] |= _bitMask[targetSquareIndex];
							break;

						case 9:
							_squarePlus_9[currentSquareIndex] |= _bitMask[targetSquareIndex];
							break;

						case -7:
							_squareMinus_7[currentSquareIndex] |= _bitMask[targetSquareIndex];
							break;

						case -9:
							_squareMinus_9[currentSquareIndex] |= _bitMask[targetSquareIndex];
							break;
					}

					lastSquareIndex = targetSquareIndex;
					targetSquareIndex += test;
				}

			}
		}


		/// <summary>
		/// Initializes black and white rook and queen move bitboards
		/// square masking bits
		/// </summary>
		/// <param name="currentSquareIndex">Index (0-63) of the square to initialize.</param>
		private void InitRookQueenMoveSquares(int currentSquareIndex)
		{
			int targetSquareIndex;
			int lastSquareIndex;
			foreach(int test in ROOK_ATTACK_SQUARE)
			{
				lastSquareIndex = currentSquareIndex;
				targetSquareIndex = currentSquareIndex + test;
				while(ValidRookQueenMove(lastSquareIndex,targetSquareIndex))
				{
					_RookMoves[currentSquareIndex] |= _bitMask[targetSquareIndex];
					_QueenMoves[currentSquareIndex] |= _bitMask[targetSquareIndex];

					// Initialize the +1,+8,-1,-8 horizontal and vertical directional
					// bitboards while we've got the computed attack squares avaialable;
					// these will be used for obstruction detection later
					switch(test)
					{
						case 1:
							_squarePlus_1[currentSquareIndex] |= _bitMask[targetSquareIndex];
							break;

						case 8:
							_squarePlus_8[currentSquareIndex] |= _bitMask[targetSquareIndex];
							break;

						case -1:
							_squareMinus_1[currentSquareIndex] |= _bitMask[targetSquareIndex];
							break;

						case -8:
							_squareMinus_8[currentSquareIndex] |= _bitMask[targetSquareIndex];
							break;
					}

					lastSquareIndex = targetSquareIndex;
					targetSquareIndex += test;
				}
			}
		}

		
		/// <summary>
		/// Initializes series of black and white king attack bitboards
		/// </summary>
		/// <param name="currentSquareIndex"></param>
		private void InitKingAttackSquares(int currentSquareIndex)
		{
			int distance;
			for(int targetSquare=0;targetSquare<TOTAL_SQUARES;targetSquare++)
			{
				distance = GetGreaterDistance(currentSquareIndex,targetSquare);
				if(distance == 1)
				{
					_KingAttacks[currentSquareIndex] |= _bitMask[targetSquare];
				}
				else if(distance <= 1)
				{
					_KingAttacks1[currentSquareIndex] |= _bitMask[targetSquare];
				}
				else if(distance <= 2)
				{
					_KingAttacks2[currentSquareIndex] |= _bitMask[targetSquare];
				}
			}
		}

		// -- GROUP END --

		// GROUP: BitBoard Manipulation Methods

		/// <summary>
		/// Updates the internal piece bitboards to show a pawn promotion.
		/// </summary>
		/// <param name="pawnSquare">Destination square for pawn.</param>
		/// <param name="promotePawnTo">Piece type to promote the pawn into (KNIGHT,BISHOP,ROOK,QUEEN)</param>
		private void UpdateBitBoardsForPromotion(int pawnSquare, Piece promotePawnTo)
		{
			PlayerTurn side = GetPieceColor(pawnSquare);
			if(side==PlayerTurn.Black)
			{
				_chessPosition.blackPawns ^= _bitMask[pawnSquare];
				switch(promotePawnTo)
				{
					case -KNIGHT:
						_chessPosition.blackKnights |= _bitMask[pawnSquare];
						break;
					case -BISHOP:
						_chessPosition.blackBishops |= _bitMask[pawnSquare];
						break;
					case -ROOK:
						_chessPosition.blackRooks |= _bitMask[pawnSquare];
						break;
					case -QUEEN:
						_chessPosition.blackQueens |= _bitMask[pawnSquare];
						break;
				}
			}
			else
			{
				_chessPosition.whitePawns ^= _bitMask[pawnSquare];
				switch(promotePawnTo)
				{
					case KNIGHT:
						_chessPosition.whiteKnights |= _bitMask[pawnSquare];
						break;
					case BISHOP:
						_chessPosition.whiteBishops |= _bitMask[pawnSquare];
						break;
					case ROOK:
						_chessPosition.whiteRooks |= _bitMask[pawnSquare];
						break;
					case QUEEN:
						_chessPosition.whiteQueens |= _bitMask[pawnSquare];	
						break;
				}
			}
		}

		/// <summary>
		/// Inverts a bitboard containing occupancy state to a mirror image of itself.
		/// </summary>
		/// <param name="occupancyState">Bitboard representation of pieces on a rank/diag/file</param>
		/// <param name="bitLength">Range of bits to invert</param>
		/// <returns>BitBoard representing the inversion of bitLength bits in 
		/// the occupancyState BitBoard
		/// </returns>
		private BitBoard InvertOccupancyBits(BitBoard occupancyState, int bitLength)
		{
			int start = 1;
			int result = 0;
			int newMask = 0;
			int bitShift = 1;
			int limit = (int)Math.Pow(2,bitLength);

			while(start < limit) // no point in going past max bits
			{
				if( (occupancyState & (BitBoard)start) != 0)
				{
					newMask = 1 << (bitLength - bitShift);
					result |= newMask;
				}
				start <<= 1; // left shift one bit
				bitShift++;
			}
		
			return (BitBoard)result;

		}

		/// <summary>
		/// Updates bitboards to reflect moves and captures if necessary
		/// </summary>
		/// <param name="fromSquare">Index (0-63) of where piece is moved from.</param>
		/// <param name="toSquare">Index (0-63) of where piece is moving to.</param>
		private void UpdateMoveBitBoards(int fromSquare, int toSquare)
		{
			Piece pieceToMove = GetPiece(fromSquare);
			Piece targetSquare = GetPiece(toSquare);

			// If the target square is occupied, update opponent's respective bitboards
			// to reflect the capture
			if(targetSquare != 0)
				UpdateCaptureBitBoards(toSquare);
			
			// Update rotated bitboards
			SetRotatedBitBoards(toSquare);
			ClearRotatedBitBoards(fromSquare);

			// Create a temp bitboard mask for "moving" the piece from bit
			// to the "to" bit location
			BitBoard clearMask = _bitMask[fromSquare] | _bitMask[toSquare];

			// Clear respective bits for the move
			if(pieceToMove > 0)
			{
				_chessPosition.whitePieces ^= clearMask;
			}
			else
			{
				_chessPosition.blackPieces ^= clearMask;
			}

			// Do the move
			switch(Math.Abs(pieceToMove))
			{
				case PAWN:
					if(pieceToMove > 0)
					{
						_chessPosition.whitePawns ^= clearMask;
					}
					else
					{
						_chessPosition.blackPawns ^= clearMask;
					}

					break;

				case KNIGHT:
					if(pieceToMove > 0)
					{
						_chessPosition.whiteKnights ^= clearMask;
					}
					else
					{
						_chessPosition.blackKnights ^= clearMask;
					}
					break;

				case BISHOP:
					_chessPosition.bishopsQueens ^= clearMask;
					if(pieceToMove > 0)
					{
						_chessPosition.whiteBishops ^= clearMask;
					}
					else
					{
						_chessPosition.blackBishops ^= clearMask;
					}
					break;

				case ROOK:
					_chessPosition.rooksQueens ^= clearMask;
					if(pieceToMove > 0)
					{
						_chessPosition.whiteRooks ^= clearMask;
					}
					else
					{
						_chessPosition.blackRooks ^= clearMask;
					}
					break;

				case QUEEN:
					_chessPosition.rooksQueens ^= clearMask;
					_chessPosition.bishopsQueens ^= clearMask;
					if(pieceToMove > 0)
					{
						_chessPosition.whiteQueens ^= clearMask;
					}
					else
					{
						_chessPosition.blackQueens ^= clearMask;
					}
					break;

				case KING:
					if(pieceToMove > 0)
					{
						_chessPosition.whiteKingSquare = toSquare;
					}
					else
					{
						_chessPosition.blackKingSquare = toSquare;
					}
					
					break;
			}

		}

		/// <summary>
		/// Updates opponent bitboards to reflect capture -- note: KINGS are not open for capture-- duh!
		/// </summary>
		/// <remarks>
		/// This method can also be used to "replace" pieces that were previously removed-- just make sure
		/// the virtual board has been updated first as it relies on GetPiece() for setting the masking bit.
		/// </remarks>
		/// <param name="toSquare"></param>
		private void UpdateCaptureBitBoards(int toSquare)
		{
			Piece capturedPiece = GetPiece(toSquare);
			BitBoard toMask = _bitMask[toSquare];

			// Reminder:  WhitePieces > 0
			//			  BlackPieces < 0
			
			// NB:  We use XOR to remove the "to" square mask bit to the assembled collection of bits
			// representing each piece set.
			if(capturedPiece > 0)
			{
				_chessPosition.whitePieces ^= toMask;
			}
			else if(capturedPiece < 0)
			{
				_chessPosition.blackPieces ^= toMask;
			}

			// Update bitboard for piece type
			switch(Math.Abs(capturedPiece))
			{
				case PAWN:
					if(capturedPiece > 0)
					{
						_chessPosition.whitePawns ^= toMask;
					}
					else
					{
						_chessPosition.blackPawns ^= toMask;
					}
					break;

				case KNIGHT:
					if(capturedPiece > 0)
					{
						_chessPosition.whiteKnights ^= toMask;
					}
					else
					{
						_chessPosition.blackKnights ^= toMask;
					}
					break;

				case BISHOP:
					if(capturedPiece > 0)
					{
						_chessPosition.whiteBishops ^= toMask;
					}
					else
					{
						_chessPosition.blackBishops ^= toMask;
					}
					break;

				case ROOK:
					if(capturedPiece > 0)
					{
						_chessPosition.whiteRooks ^= toMask;
					}
					else
					{
						_chessPosition.blackRooks ^= toMask;
					}
					break;

				case QUEEN:
					if(capturedPiece > 0)
					{
						_chessPosition.whiteQueens ^= toMask;
					}
					else
					{
						_chessPosition.blackQueens ^= toMask;
					}
					break;
			}
		}

		/// <summary>
		/// Rotates a bitboard by 90 degrees to the right, mapping all pieces toward the left.
		/// </summary>
		/// <param name="source">Source bitboard to rotate.</param>
		/// <param name="xDegrees">Enum indicating degree shift to perform on bitboard.</param>
		/// <returns>BitBoard representing a rotation of the source BitBoard mapped by a
		/// specified number of degrees.
		/// </returns>
		private BitBoard GetRotatedBitBoard(BitBoard source, RotateBitBoardBy xDegrees)
		{
			BitBoard start = 1;
			BitBoard result = 0;
			int squareIndex = 0;

			while(squareIndex < 64)
			{
				if( (start & source) != 0 )
				{
					switch(xDegrees)
					{
						case RotateBitBoardBy.Right90Degrees:
							result |= _bitMask[RotatedBitBoard.Right90[squareIndex]];
							break;

						case RotateBitBoardBy.Left90Degrees:
							result |= _bitMask[RotatedBitBoard.Left90[squareIndex]];
							break;

						case RotateBitBoardBy.Right45Degrees:
							result |= _bitMask[RotatedBitBoard.Right45[squareIndex]];
							break;

						case RotateBitBoardBy.Left45Degrees:
							result |= _bitMask[RotatedBitBoard.Left45[squareIndex]];
							break;

						case RotateBitBoardBy.A8H1Map:
							result |= _bitMask[RotatedBitBoard.DiagA8H1Map[squareIndex]];
							break;

						case RotateBitBoardBy.A1H8Map:
							result |= _bitMask[RotatedBitBoard.DiagA1H8Map[squareIndex]];
							break;

						default:
							throw new ArgumentException("Rotation argument is not in allowable range;  must be specified by the enumerated type RotateBitBoardBy.",
								"xDegrees");
					}
						
				}

				squareIndex++;
				start <<= 1;
			}

			return result;
		}
		// -- GROUP END --

		// GROUP: BitBoard Analysis Methods
		/// <summary>
		/// Verifies that the proposed rook move or capture is valid.
		/// </summary>
		/// <param name="fromSquare">Square index (0-63) piece is moving FROM</param>
		/// <param name="toSquare">Square index (0-63) piece is moving TO</param>
		/// <returns>TRUE if the move is legal for a Rook piece.</returns>
		private bool CheckRookMove(int fromSquare, int toSquare)
		{
			BitBoard toBitBoard = _bitMask[toSquare];

			// Ensure move is legal
			if((_RookMoves[fromSquare] & toBitBoard) == 0)
			{
				return false;
			}
			else	// move is toward a valid square
			{
				// Evaluate for valid attack squares
				BitBoard controlledSquares = GetRookAttackSquares(fromSquare);
				if((toBitBoard & controlledSquares) == 0)
					return false;
			}

			return true;

		}
		
		
		/// <summary>
		/// Verifies that proposed bishop move or capture is valid.
		/// </summary>
		/// <param name="fromSquare">Square index (0-63) piece is moving FROM</param>
		/// <param name="toSquare">Square index (0-63) piece is moving TO</param>
		/// <returns>TRUE if the move is a legal for a Bishop piece.</returns>
		private bool CheckBishopMove(int fromSquare, int toSquare)
		{
			BitBoard toBitBoard = _bitMask[toSquare];

			// Ensure move is legal
			if((_BishopMoves[fromSquare] & toBitBoard) == 0)
			{
				return false;
			}
			else
			{
				BitBoard controlledSquares = GetBishopAttackSquares(fromSquare);
				if((toBitBoard & controlledSquares) == 0)
					return false;
			}

			return true;
		}

		
		/// <summary>
		/// Returns a bitboard of all squares a given rook is attacking
		/// </summary>
		/// <param name="currentSquare">Index (0-63) of attacking rook.</param>
		/// <returns>BitBoard representing the available rank and file squares for attack.</returns>
		private BitBoard GetRookAttackSquares(int currentSquare)
		{			
			BitBoard fileControlledSquares = GetFileControlledSquares(currentSquare);
			BitBoard rankControlledSquares = GetRankControlledSquares(currentSquare);
			BitBoard result = fileControlledSquares | rankControlledSquares;
			return result;
		}

		/// <summary>
		/// Returns a bitboard of all file squares a rook on a given square is attacking.
		/// </summary>
		/// <param name="currentSquare">Index (0-63) of attacking rook.</param>
		/// <returns>BitBoard representing the available file squares for attack.</returns>
		private BitBoard GetFileControlledSquares(int currentSquare)
		{
			// Work out the controlled rank squares - 
			// This is just the result of looking up the valid moves a rook can make from
			// the currentSquare and ANDing them with all the pieces on the board.
			// We then need to shift the bits for the file "UP" to the top of the board so
			// we can use the "state" as an index for finding the valid squares that the rook
			// is attacking.
			BitBoard allPieces = _chessPosition.whitePieces | _chessPosition.blackPieces;
			BitBoard validSquares = _RookMoves[currentSquare] & allPieces;
			int fileState = (int)(validSquares >> RotatedBitBoard.ShiftBitsIndex[currentSquare]) & 255;
			BitBoard fileControlledSquares =(_FileAttacks[currentSquare,fileState] << RotatedBitBoard.ShiftBitsIndex[currentSquare]);
			
			return fileControlledSquares;
		}

		/// <summary>
		/// Returns a BitBoard of all rank squares a rook on a given square is attacking.
		/// </summary>
		/// <param name="currentSquare">Index (0-63) of attacking rook.</param>
		/// <returns>BitBoard representing the available rank squares for attack.</returns>
		private BitBoard GetRankControlledSquares(int currentSquare)
		{
			// Rotate the bitboard and work out the controlled rank squares -
			// Pretty much the same deal as above, however we now have the added fun of
			// rotating the file so that its horizontal- hence the copious requests for 
			// rotated bitboards.
			BitBoard allPieces = _chessPosition.whitePieces | _chessPosition.blackPieces;
			allPieces = GetRotatedBitBoard(allPieces,RotateBitBoardBy.Right90Degrees);
			BitBoard validSquares = GetRotatedBitBoard(_RookMoves[currentSquare],RotateBitBoardBy.Right90Degrees) & allPieces;

			currentSquare = RotatedBitBoard.Right90[currentSquare];
			int rankState = (int)(validSquares >> RotatedBitBoard.ShiftBitsIndex[currentSquare]) & 255;
			BitBoard rankControlledSquares = _RankAttacks[currentSquare,rankState] << RotatedBitBoard.ShiftBitsIndex[currentSquare];

			// Now undo the rotation we applied with a left turn 90 degrees - 
			// OR the results together for a comprehensive map of the controlled squares
			rankControlledSquares = GetRotatedBitBoard(rankControlledSquares,RotateBitBoardBy.Left90Degrees);

			return rankControlledSquares;
		}
		
		/// <summary>
		/// Returns a bitboard of all squares a given bishop is attacking
		/// </summary>
		/// <param name="currentSquare"></param>
		/// <returns></returns>
		private BitBoard GetBishopAttackSquares(int currentSquare)
		{
			// Process:
			// 1)	Rotate and map over the required bitboard -- the A8H1 diagonal and
			//		the A1H8 diagonal
			// 2)	Calculate the necessary shift to move the target diagonal to the
			//		first row of the bitboard
			// 3)	Look up the length of the diagonal from arrays
			// 4)	Look up bitmask for the square or just AND with enough 1's to
			//		mask the length of the diagonal.  This renders the occupancyState
			// 5)	Look up the available target squares using the index of:
			//		[currentSquare][occupancyState]
			//		This renders targetSquares
			// 6)	targetSquares ~= allPieces renders finalResult
                                                 
			BitBoard allPieces = _chessPosition.whitePieces | _chessPosition.blackPieces;
			BitBoard occupiedSquares = _BishopMoves[currentSquare] & allPieces;
			
			// Rotate the bitboards for each diagonal
			BitBoard occupiedL45= GetRotatedBitBoard(occupiedSquares,RotateBitBoardBy.Left45Degrees);
			BitBoard occupiedR45 = GetRotatedBitBoard(occupiedSquares,RotateBitBoardBy.Right45Degrees);
			
			// Now we need to lookup the required shifts to move the diagonals into
			// the 8 least significant bits for state indexing
			int bitShiftA8H1 = RotatedBitBoard.DiagonalShiftA8H1[currentSquare];
			int bitShiftA1H8 = RotatedBitBoard.DiagonalShiftA1H8[currentSquare];          
			occupiedL45 >>= bitShiftA8H1;
			occupiedR45 >>= bitShiftA1H8;

			// Calculate masking bits and apply to rotated occupancy bitboards to get occupancyState
			int maskL45 = (int)Math.Pow(2,RotatedBitBoard.DiagonalLengthA8H1[currentSquare])-1;
			int maskR45 = (int)Math.Pow(2,RotatedBitBoard.DiagonalLengthA1H8[currentSquare])-1;
			BitBoard l45OccupancyState = occupiedL45 & (BitBoard)maskL45;
			BitBoard r45OccupancyState = occupiedR45 & (BitBoard)maskR45;
			l45OccupancyState = InvertOccupancyBits(l45OccupancyState,RotatedBitBoard.DiagonalLengthA8H1[currentSquare]);
			r45OccupancyState = InvertOccupancyBits(r45OccupancyState,RotatedBitBoard.DiagonalLengthA1H8[currentSquare]);

			// Index controlled target squares using currentSquare and occupancyStates
			BitBoard a8h1Controlled = _DiagonalA8H1Attacks[currentSquare][l45OccupancyState];
			BitBoard a1h8Controlled = _DiagonalA1H8Attacks[currentSquare][r45OccupancyState];
			
			// Invert the occupancy bits so that they'll be oriented correctly after shifting
			a8h1Controlled = InvertOccupancyBits(a8h1Controlled,RotatedBitBoard.DiagonalLengthA8H1[currentSquare]);
			a1h8Controlled = InvertOccupancyBits(a1h8Controlled,RotatedBitBoard.DiagonalLengthA1H8[currentSquare]);

			// Shift back into original locations and undo rotations
			a8h1Controlled <<= bitShiftA8H1;
			a1h8Controlled <<= bitShiftA1H8;
			a8h1Controlled = GetRotatedBitBoard(a8h1Controlled,RotateBitBoardBy.A8H1Map);
			a1h8Controlled = GetRotatedBitBoard(a1h8Controlled,RotateBitBoardBy.A1H8Map);

			// Combine controllable squares for a8h1 and a1h8 diagonals
			BitBoard totalControl = a8h1Controlled | a1h8Controlled;

			return totalControl;

		}

		/// <summary>
		/// Returns the piece position bitboard for a given type for the current position.
		/// </summary>
		/// <param name="pieceType">Piece type to fetch.</param>
		/// <returns>BitBoard representation of the pieces</returns>
		private BitBoard GetPieceTypeBitBoard(Piece pieceType)
		{
			switch(pieceType)
			{
				case PAWN:
					return _chessPosition.whitePawns;
				case -PAWN:
					return _chessPosition.blackPawns;
				case KNIGHT:
					return _chessPosition.whiteKnights;
				case -KNIGHT:
					return _chessPosition.blackKnights;
				case BISHOP:
					return _chessPosition.whiteBishops;
				case -BISHOP:
					return _chessPosition.blackBishops;
				case ROOK:
					return _chessPosition.whiteRooks;
				case -ROOK:
					return _chessPosition.blackRooks;
				case QUEEN:
					return _chessPosition.whiteQueens;
				case -QUEEN:
					return _chessPosition.blackQueens;
				case KING:
					return _bitMask[_chessPosition.whiteKingSquare];
				case -KING:
					return _bitMask[_chessPosition.blackKingSquare];
				default:
					return 0;
			}
		}
		// -- GROUP END --
	}
}
